文章目录
什么时候需要对类进行初始化?
有且只有以下 5 种情况必须立即对类进行“初始化”
- 遇到 new、getstatic、putstatic 或 invokestatic 这 4 条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这 4 条指令的最常见的 Java 代码场景是:
使用 new 关键字实例化对象的时候、读取或设置一个类的静态字段(被 final 修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候
。 - 使用 java.lang.reflect 包的方法
对类进行反射调用
的时候,如果类没有进行过初始化,则需要先触发其初始化。 - 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则
需要先触发其父类的初始化
。 - 当虚拟机启动时,用户需要指定一个要
执行的主类
(包含 main() 方法的那个类),虚拟机会先初始化这个主类。 - 当使用
JDK1.7 的动态语言支持
时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果 REF_getStatic、REF_putStatic、REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。
说一下类加载的过程
- 加载
- 验证
- 准备
- 解析
- 初始化
请参考:类加载机制(二):类加载的过程
说一下对象创建的过程
- 类加载检查
- 分配对象内存
- 对象实例数据初始化为零值
- 设置对象头
什么是类加载器,常见的类加载器有哪些?
什么是双亲委派模型?它的工作过程是怎样的?
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。子类加载器和父类加载器不是以继承(Inheritance)的关系来实现,而是通过组合(Composition)关系来复用父加载器的代码。
列举一些你知道的打破双亲委派机制的例子,为什么要打破?
Java 是解释执行还是编译执行?
- 在部分的商用虚拟机中,Java 程序最初是通过解释器进行解释执行的。当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”。为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler,简称 JIT 编译器)。
- 解释器与编译器两者各有优势:
当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。
当程序运行环境中内存资源限制较大,可以使用解释执行节约内存,反之可以使用编译执行来提升效率(因为即时编译器编译后的代码存在了方法区)。
请参考:【运行期优化】
什么是 JVM 内存模型?
请参考:【Java 内存模型与线程】