“代码编译的结果从本地机器码变为字节码,是存储格式发展的一小步,但却是语言发展的一大步”,来自《深入理解JAVA虚拟机》一书中,后续的一系列关于jvm的文章主要来自
编译JAVA源代码由三个进程组成:
1、源代码编译机制。
2、班级加载机制
三、班级执行机制
这里主要介绍两种机制:编译和类加载。
一、源代码编译
代码的编译由JAVA源代码编译器完成。 主要将源代码编译为字节码文件(class文件)。 字节码文件格式主要分为常量池和方法字节码两部分。
二、班路
类的生命周期加载到虚拟机的内存中,然后从内存中卸载并退出。 流程有七个阶段,在初始化之前是类加载的一部分
加载----验证----准备----分析----初始化----使用----卸载
系统可以在第一次使用类时加载类,也可以使用预加载机制加载类。 运行java程序时,java虚拟机进程将启动。 运行两次的java程序位于两个不同的JVM进程中,两个JVM之间不共享数据。
1、加载阶段
在此过程中加载是类加载机制的一个阶段。 这两个概念不要混淆。 需要在这一阶段完成的工作包括:
1 )从类的完全限定名称中获取定义该类的二进制字节流。
2 )将该字节流所代表的静态存储结构转换为方法区域的运行时数据结构。
3 )在java堆中生成表示该类的Class对象,作为访问方法区域中这些数据的入口。
第一点没有给出从哪里获取类的二进制流,如何获取,所以这个领域给我的开发人员留下了很大的空间。 这在后面的班级加载器中有介绍。
2、准备阶段
在该阶段正式向类变量(用static限定的变量)分配内存,设定类变量的初始值。 此内存分配发生在方法区域。
1、请注意这里没有对实例变量进行内存分配。 实例变量在实例化对象时与对象一起分配给JAVA堆。
2、这里设定的初始值通常是指数据类型的零值。
隐私静态Int a=3;
该类变量a的准备阶段后的值为0,将3代入变量a是初始化阶段。
3、初始化阶段
初始化是类加载机制的最后一步,该机制实际上开始执行类中定义的JAVA程序代码。 在前一准备阶段,类变量被分配了一次系统请求的初始值。 在初始化阶段,最重要的是初始化类变量,注意父子类之间各资源的初始化顺序。
要在java类中为类变量指定初始值,请1、在声明类变量时指定初始值; 2 .使用静态初始化块为类变量指定初始值。
初始化时机
1 )创建类实例时,分别使用1、new关键字创建实例; 2 .通过反射创建实例: 3 .用反序列化方式创建实例。
新测试(;
class.forname(「com.mengDD.test "
2 )调用某个类的类方法(静态方法)
Test.doSomething (;
3 )访问某个类或接口的类变量,或为该类变量赋值。
int b=Test.a;
Test.a=b;
4 )初始化某个类的子类。 初始化子类时,将初始化该子类的所有父类。
5 )直接使用java.exe命令运行主类。
上述几种方法不仅自动初始化一个类,而且访问其他类的方法据说不会发生被称为被动引用的类的初始化。
1、子类引用父类的静态变量,不初始化子类。
公共类
{公共静态输入a=123; 静态{
system.out.println (supclassinit );
}
} publicclasssubclassextendssupclass
静态{2}
system.out.println (subclass init );
}
}公共类
{publicstaticvoidmain[]args]
{
system.out.println(subclass.a;
}
}
执行结果:
supclass init123
2 .在数组中定义引用类,不引起这种初始化
公共类
{公共静态输入a=123; 静态{
system.out.println (supclassinit );
}
}公共类
{publicstaticvoidmain[]args]
{
SupClass[] spc=new SupClass[10];
}
}
执行结果:
3、引用常量时,不会触发该类的初始化
公共类群集
{ publicstaticfinalstringa=' migu '; 静态{
system.out.println (constclassinit );
}
}公共类stestmain
{publicstaticvoidmain[]args]
{
系统. out.println (const class.a );
}
}
执行结果:
微软公司
如果用final限定某个类变量,则该类变量的值在编译时必须放入常量池中,因此访问该类变量时与直接从常量池中检索的值相同,并且该类尚未初始化。
初始化步骤
1 .如果类尚未加载并连接,程序将首先加载并连接类。
2 .如果未加载该类的直接父类,则首先初始化该直接父类。
3、类中有初始化语句时,系统依次执行这些初始化语句。
在第二个步骤中,如果有直接的父类和直接的父类,系统将再次重复这三个步骤来初始化父类,并类推JVM首先初始化的始终是java.lang.Object类。 当程序主动使用其中一个类时,它可以确保该类和所有父类都被初始化。