|
[当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到JVM。]()
[package com.tuling.jvm; public class Math { public static final int initData = 666; public static User user = new User(); public int compute() { //一个方法对应一块栈帧内存区域 int a = 1; int b = 2; int c = (a + b) * 10; return c; } public static void main(String[] args) { Math math = new Math(); math.compute(); } } ]()

[其中loadClass的类加载过程有如下几步:]()
[加载 >> 验证 >> 准备 >> 解析 >> 初始化 >> ]()使用 >> 卸载
[· 加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new对象等等,在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口]()
[· 验证:校验字节码文件的正确性]()
[· 准备:给类的静态变量分配内存,并赋予默认值]()
[· 解析:将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针或句柄等(直接引用),这是所谓的静态链接过程(类加载期间完成),动态链接是在程序运行期间完成的将符号引用替换为直接引用,下节课会讲到动态链接]()
[· 初始化]():对类的静态变量初始化为指定的值,执行静态代码块

[类被加载到方法区中后主要包含 运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应class实例的引用等信息。]()
[类加载器的引用]():这个类到类加载器实例的引用
[对应class实例的引用]():类加载器在加载类信息放到方法区中后,会创建一个对应的Class 类型的对象实例放到堆(Heap)中, 作为开发人员访问方法区中类定义的入口和切入点。
[注意,]()主类在运行过程中如果使用到其它类,会逐步加载这些类。
[jar]()包或war包里的类不是一次性全部加载的,是使用到时才加载。
public class TestDynamicLoad {- static {
- System.out.println("\*\*\*\*\*\*\*\*\*\*\*\*\*load TestDynamicLoad\*\*\*\*\*\*\*\*\*\*\*\*");
- }
- public static void main(String[] args) {
- new A();
- System.out.println("\*\*\*\*\*\*\*\*\*\*\*\*\*load test\*\*\*\*\*\*\*\*\*\*\*\*");
- B b = null; //B不会加载,除非这里执行 new B()
- }
复制代码 }
class A {static {System.out.println("*************load A************");}- public A() {
- System.out.println("\*\*\*\*\*\*\*\*\*\*\*\*\*initial A\*\*\*\*\*\*\*\*\*\*\*\*");
- }
复制代码 }
class B {static {System.out.println("*************load B************");}- public B() {
- System.out.println("\*\*\*\*\*\*\*\*\*\*\*\*\*initial B\*\*\*\*\*\*\*\*\*\*\*\*");
- }
复制代码 }
运行结果:*************load TestDynamicLoad*************************load A************ |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|