深入JVM(一)

292 阅读29分钟

java 字节码技术

java bytecode由单字节(byte)的指令组成,理论上最多支持256个操作码(opcode)。实际上java只使用200左右的操作码,还有一些操作码保留给调试操作。

根据指令的性质,主要分为四大类:

1、栈操作指令,包括与局部变量交互的指令。

例如3: iconst2 将常量2压入栈中

2、程序流程控制指令。

例如1:if_icmpne

3、对象操作指令,包括方法调用指令。

例如2:invokevirtual:用于调用非私有实例方法

  1. invokestatic:用于调用静态方法。
  2. invokespecial:用于调用私有实例方法、构造器,以及使用 super 关键字调用父类的实例方法或构造器,和所实现接口的默认方法。
  3. invokevirtual:用于调用非私有实例方法。
  4. invokeinterface:用于调用接口方法。
  5. invokedynamic:用于调用动态方法。

4、算数运算以及类型转换指令。

    例如4:i2d int转double

5、其他:

a、异常处理

from->to 代表监控代码位置。

target:异常处理开始位置。

type:代表触发的异常类型。

b、反射的字节码实现

    invokevirtual Method.invoke     // 反射调用复制代码

java类加载器

类的生命周期:

1.加载(Loading):找 Class 文件

2.验证(Verification):验证格式、依赖

3.准备(Preparation):为静态字段分配内存、解析出方法表方法表,为其他类及其方法、字段所对应的具体地址分配符号引用。

4.解析(Resolution):符号解析为引用(如果符号引用指向未加载的类会触发加载)。

5.初始化(Initialization):构造器、静态变量赋值、静态代码块。

类加载时机

  1. 当虚拟机启动时,初始化用户指定的主类;
  2. 当遇到用以新建目标类实例的 new 指令时,初始化 new 指令的目标类;
  3. 当遇到调用静态方法的指令时,初始化该静态方法所在的类;
  4. 当遇到访问静态字段的指令时,初始化该静态字段所在的类;
  5. 子类的初始化会触发父类的初始化;
  6. 如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化;
  7. 使用反射 API 对某个类进行反射调用时,初始化这个类;
  8. 当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类。

不会初始化(可能被加载)

1.通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。

2.定义对象数组,不会触发该类的初始化。

3.常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。

4.通过类名获取 Class 对象,不会触发类的初始化,Hello.class 不会让 Hello 类初始

化。

5.通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触

发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。Class.forName

(“jvm.Hello”)默认会加载 Hello 类。

6.通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作(加载了,但是

不初始化)。

java类加载器

启动类加载器(bootstrapClassLoader)负责加载最为基础、最为重要的类,比如存放在 JRE 的 lib 目录下 jar 包中的类(以及由虚拟机参数 -Xbootclasspath 指定的类)。除了启动类加载器之外,另外两个重要的类加载器是扩展类加载器(extension class loader)和应用类加载器(application class loader),均由 Java 核心类库提供。

扩展类加载器(ExtClassLoader)的父类加载器是启动类加载器。它负责加载相对次要、但又通用的类,比如存放在 JRE 的 lib/ext 目录下 jar 包中的类(以及由系统变量 java.ext.dirs 指定的类)。

应用类加载器(AppClassLoader)的父类加载器则是扩展类加载器。它负责加载应用程序路径下的类。(这里的应用程序路径,便是指虚拟机参数 -cp/-classpath、系统变量 java.class.path 或环境变量 CLASSPATH 所指定的路径。)默认情况下,应用程序中包含的类便是由应用类加载器加载的。

特点:双亲委托、负责依赖、缓存加载。