JVM

58 阅读2分钟

类加载与字节码技术 

魔数用于判断文件是否为class文件 

通过javap命令反编译class文件 

字节码指令包括入操作数栈指令,出栈指令,以及操作指令如iadd和方法调用 

构造方法包括分为类构造以及对象构造方法,类构造cinit方法在类加载的初始化阶段阶段调用,主要执行静态代码块以及静态成员赋值。而对象构造则执行原始构造方法 

方法调用本质是通过对象头找到class对象,再通过class对象的vtable找到方法的具体地址 

异常处理通过exception table异常表实现,异常表由from,to,target以及type4列组成 

加syn锁时,异常表的target设置了解锁代码,所以syn锁是自动释放的 

匿名内部类是一种编译期语法糖,引用的局部变量是构造方法的入参 

类加载分为加载,链接以及初始化阶段三个阶段,加载是懒惰加载,访问class对象之前不会加载,链接主要是静态类型默认值以及符号引用替换为直接引用,初始化则是执行cinit方法,不是所有类加载都会初始化,如果只是创建类对象的数组,则不会发生初始化 

类加载器有bootstrap,extension以及app三个,遵循双亲委派原则,加载方法依次是:loadClass封装双亲委派逻辑->findClass->defineClass方法装载字节码为class对象->classWrite对象构建字节码 

运行期的优化包括JIT即时编译以及反射优化。JIT即分层编译热点代码以及逃逸分析,逃逸分为全局逃逸如成员对象以及参数逃逸如方法入参对象,只在方法内部创建和使用的对象则没有逃逸,没有逃逸的对象则可以进行锁消除以及栈上分配优化 

内存结构 

栈由栈帧组成,栈帧包括局部变量表,操作数栈,动态链接,锁记录以及方法返回地址

本地方法栈执行native方法

程序计数器表示线程执行位置

堆的xmx和xms的值设置需要一样,xmn表示新生代大小

方法区用于存储class文件信息以及运行时常量池,运行时常量池加载了常量池并将符号地址转化为真实地址

常量池中的字符串是符号,使用时转换为字符串对象放入串池中,串池在堆中

直接内存通过ByteBuffer对象分配,并在ByteBuffer回收时设置虚引用以回收直接内存,底层是通过unsafe类分配和回收

GC

方法区也有GC,如类没有任何对象时

对象是否存活可以通过引用计数法以及可达性分析判断,栈帧中局部变量表引用的对象是常见的GCRoot。标记过程可以并发标记,并发标记的增量更新阶段会进入STW

引用包括强引用如普通变量赋值,软引用如反射,弱引用如threadLocalMap的key以及虚引用即用于直接内存的回收

回收算法包括清除算法涉及碎片,整理算法涉及引用地址修改以及复制算法涉及from和to占用两个空间

分代回收时如果对象年龄达到15则会放入老年代,老年代的回收是fullGC,新生代中survivor的目的就是为了减少FullGC。如果一个对象放不进eden则直接放入老年代

回收器包括串行,1.8默认的吞吐量优先的ParallelGC,低延时优先的CMS以及1.9默认的用于替代CMS的G1,G1可以设置STW目标,GC调优的两个方向为高吞吐量和低延时