JVM解析
1. Java源码编译机制
Java编译由三部分组成:
1) 分析和输入到符号表
2) 注解的处理
3) 语义分析和生成class文件
生成的class文件有以下几部分:
A. 结构信息
Class文件格式版本号及各部分的数量与大小信息
B. 元数据
对应于java源码中声明及常量的信息。包含类/继承的超类/实现的接口的声明信息、域与方法的声明信息和常量池
C. 方法信息
对应java源码中的语句和表达式对应的信息。包括字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试符号信息。
2. 类加载机制
1) Bootstrap ClassLoader
负责加载JAVA_HOME中的jre/lib/rt.jar里所有的class,由c++实现,不是ClassLoader子类
2) Extension ClassLoader
负责加载java平台中扩展功能的一些jar包,包括JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
3) App ClassLoader
负责加载ClassPath中指定的jar包及目录中的class
4) Custom ClassLoader
属于应用程序根据自身需要自定义的ClassLoader,比如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
5) 加载顺序
加载过程中会先检查类是否被加载,检查顺序是自底向上,从Custom ClassLoader到Bootstrap ClassLoader逐层检查,只要某个calssloader已加载就视为已加载此类,保证此类只被所有ClassLoader加载一次。
而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
3. 类执行机制
JVM是基于堆栈的虚拟机。JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
JVM执行class字节码,线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。
4. 堆内存管理及垃圾回收机制
1) 堆内存
通过new创建的对象的内存都在堆中分配
2) 栈内存
3) 堆内存与栈内存说明
基础数据类型直接在栈空间分配,方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收。
引用数据类型,需要用new来创建,既在栈空间分配一个地址空间,又在堆空间分配对象的类变量。
方法的引用参数,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完成后从栈空间回收。
局部变量new出来时,在栈空间和堆空间中分配空间,当局部变量生命周期结束后,栈空间立刻被回收,堆空间区域等待GC回收。
方法调用时传入的literal参数,先在栈空间分配,在方法调用完成后从栈空间收回。
字符串常量、static在DATA区域分配,this在堆空间分配。
数组既在栈空间分配数组名称,又在堆空间分配数组实际的大小。
4) 本地方法栈
Native方法 jni
5) 方法区
它保存方法代码(编译后的java代码)和符号表。存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(Permanet Generation)来存放方法区
6) 垃圾回收机制
Java的所有释放都由 GC 来做,GC除了做回收内存之外,另外一个重要的工作就是内存的压缩