目录 start

  1. 字节码以及类加载
    1. 编译优化
    2. 字节码
      1. 常量池
    3. 类加载机制
      1. 类加载器
      2. 加载和连接
      3. 方法句柄
  2. 反编译
    1. JD
    2. Jad
  3. 字节码相关框架
  4. 热更新

目录 end|2019-10-19 17:04|


字节码以及类加载

个人相关代码

相关项目

Apache bcel
cglib
javassist

编译优化

由源文件 .java 编译成 .class 文件

类中定义的常量 如果是字面值, 其他引用这个常量的地方编译后会被替换成字面值, 该常量属性的 get 方法也是直接返回字面值
字面值就是无需运算的值, 而不是表达式 例如 final int num = 2; 反例 final int num = 3>2?1:2;

字节码

参考博客: 学会阅读Java字节码

字节码是程序的中间表达形式,源码和机器码之间的产物 字节码是由源文件执行javac产生的
某些高级语言特性(语法糖)在字节码中给去掉了,例如循环结构,会转换成为分支指令

  • 每个操作都由一个字节表示,因此叫做字节码
  • 字节码是一种抽象表示方法 字节码进一步编译得到机器码

  • javap -c -p class文件 反编译字节码文件,-p 能看到私有属性

    • 输出所有的属性以及类的定义信息
    • 静态块
    • 构造方法
    • 方法信息
    • 静态属性信息
    • 静态方法信息

常量池

常量池是为类文件中的其他常量元素提供快捷访问方式的区域。对于JVM来说常量池相当于符号表
参考博客

  • javap -v class文件 输出很多额外信息,# 开头的就是常量池信息

    图
  • [ ] 理解常量池 以及使用场景

类加载机制

  • 类的生命周期
    • 加载 Loading -> 验证 Verification -> 准备 Preparation -> 解析 Resolution -> 初始化 Initialization -> 使用 Using -> 卸载 Unloading
    • 验证 准备 解析, 统称为 连接 Linking

类加载器

图
  • Java平台经典类加载器:

    • 根(引导)加载器: 通常在VM启动后不久就实例化,作用是加载系统的基础JAR(主要是rt.jar),并且不做验证工作
    • 扩展类加载器: 加载安装时自带的标准扩展,一般包括安全性扩展
    • 应用或系统类加载器: 应用最广泛的类加载器,负责加载应用类,在大多SE环境中主要工作是由他完成
    • 定制类载器: 为了企业框架定制的加载器
  • BootStrap ClassLoader(启动类加载器):一般负责加载系统的核心类,如,rt.jar中的Java类

  • Extendsion ClassLoader(扩展类加载器):用于加载%JAVA_HOME%/lib/ext/*.jar中的Java类
  • App ClassLoader(应用类加载器,系统类加载器):用于加载用户程序的类
  • 自定义的ClassLoader:加载一些特殊途径的类,一般也是用户类
JavaClassLoader
JavaClassLoader

注意: 例如在读取类路径下文件时,可以通过 .getClassLoader().getResourceAsStream("app.properties") 但是如果类对象是由 BootStrap 类加载器加载的, getClassLoader()将返回 null

加载和连接

图

参考博客: 第七章.虚拟机类加载机制
加载

  • 这个过程就是读取字节码文件,创建一个字节数组装在这些内容,加载结束后这个对象还不能直接调用

连接

  • 加载完成后,类必须连接起来,分为三步:验证,准备,解析。
    • 验证:
      • 验证文件的合理性,完整性检查,检查常量池,方法的字节码检查。主要的:
      • 是否所有方法都遵守访问控制关键字的限定
      • 方法调用的参数个数和静态类型是否正确
      • 确保字节码不会试图滥用堆栈
      • 确保变量使用之前被正确初始化了
      • 检查变量是否仅被赋予恰当类型的值
    • 准备:
      • 分配内存,准备初始化类中的静态变量,但不会现在就初始化,也不会执行任何VM字节码
    • 解析:
      • 促使VM检查类文件中所引用的类型是不是都是已知的类型。如果有运行时有未知的类型,那又要引发一次类加载过程
      • 当需要加载的类全部加载解析完毕后,VM就可以初始化最初那个加载的类了。
      • 这时所有的静态变量都可以进行初始化,所有静态代码块都会运行,这一步完成后,类就能使用了

方法句柄

主要用于反射 用到再学

图

反编译

JD

JD

Jad

https://varaneckas.com/jad/


字节码相关框架

asm
javassist


热更新

通过替换 class 实现不停机热更新, 但是还有有局限性, 类结构, 方法签名不能有改变

Spring hot swapping

  1. Instrumentation
  2. 自定义类加载器
  3. OSGI 热插拔接口

Instrumentation 新功能
基于Java Instrument的Agent实现
Java 5 特性 Instrumentation 实践
java组件中的热插拔(osgi)
agentmain 方式

相关项目:

game-hot-update https://www.cnblogs.com/wgslucky/p/9127681.html
groovy hotswap demo