######内存区域划分
-
程序计数器 线程私有
线程私有 用于记录当前线程执行代码的位置,如果在执行native方法,则此计数器为空
此区域不会产生内存溢出 -
java虚拟机栈 -xss
线程私有,每个方法执行时会创建栈帧,用于记录局部变量、方法出口等信息
栈帧在方法执行时会有出栈入栈过程代表着方法的执行过程
栈溢出: 线程请求的栈深度大于虚拟机的深度抛出
内存溢出:栈长度不可扩展 递归调用方法 -
本地方法栈
使用native方法服务 -
java 堆 -Xmx -Xms
线程共享 存放对象实例
内存溢出:循环创建对象 -
方法区(jdk8之前为永久代,jdk8及以后为metaspace)-XX:PermSize -XX:MaxPermSize
线程共享,存储类信息、常量、静态变量等数据
类的版本 字段、方法、接口
溢出:通过反射不断实例化动态类 -
运行时常量池(属于方法区中的一块)
存放编译器生成的各种字面量和符号引用
String,intern()方法 相当于将字符串对象搬进常量池-XX:+HeapDumpOnOutOfMemoryError
可以让虚拟机在内存溢出时dump出当前内存堆转储存快照
#####虚拟机及垃圾算法
a.引用计数法
在对象中添加一个引用计数器,当有地方引用这个对象时,加一,引用失效时减一,
引用为零时奖杯回收(jvm不使用,无法解决相互引用的问题)
b.可达性分析算法
对GCroot进行向下搜索,发现对象不可用时将被清除
可被识别为GCroot的对象:
虚拟机栈
方法的类属性引用的对象
常量引用的对象
本地方法栈引用的对象
回收算法:
标记清除算法 单线程
效率问题 会暂停使用线程 进行标记,将可以清除的对象打上标记 在进行清除
复制算法
空间问题 分成俩俩块区域,先标记,将标记存活的对象复制到另一区域,先前区域清空
标记-整理算法
分代收集算法
老对象长期存活在老年代,大对象直接进老年代
垃圾回收器:
serial 单线程操作 会暂停用户线程,进行回收
parnew 多线程 多个回收器进行回收 在性能上并不一定比serial强
parallel 采用复制算法(新生代收集器) 多线程 相比parnew提高吞吐量
吞吐量:cpu用于运行用户代码的时间与cpu消耗的总时间的比值
= (用户代码执行的时间 )/(用户执行的时间+ 垃圾回收所占的时间 )
-XX :MaxGcPauseMillils 垃圾收集器最大停顿时间
-XX: GCTimeRatio:吞吐量大小
cms
g1
#####jdk常用工具
#####类加载机制
#######class文件组成
- javac 编译java代码
- javap -c 反编译java文件 打印助记符
- javap -verbose 打印更多信息 分析class字节码的魔数、版本号、常量池、类信息、类的构造方法、类的方法信息、类的变量及成员变量信息。
使用UE查看class二进制文件
#####字节码整体结构
1.魔数: 所有class文件的魔数(前四个字节)为固定值:CA FE BA BE
2.小版本号: 2个字节
3.主版本号:2个字节 jdk1.0的主版本号为45,往后的版本每增加一个版本这个值加一,比如jdk1.8的值为52
4.常量池(2+n个字节):紧接着主版本后后面,存储java类的资源,java中定义的方法和变量信息、字面量及符号引用,final修饰的常量,字段和方法的名称和描述等
常量池结构:常量池主要由常量池数量和常量池数组共同组成,常量池数量跟在版本后后面,2个字节,常量池数组跟在常量池数量后面,与数组不同,
常量池数组中不同的元素的类型、结构不同,长度也不同。
但是,每一个元素的第一个数据都是一个标志位u1,占一个字节。jvm解析常量池时,会根据这个u1类型来获取元素的具体类型。
常量池数组元素的个数 = 常量池数 - 1
常量池的索引从1开始,常量池数据类型11种
在jvm规范中,每个变量字段都有描述信息,描述信息主要的作用是描述字段的数据类型、方法的参数列表(包括数量、类型、顺序)与返回值,根据描述规则,
基本数据类型和代表返回值的void类型都用一个大写字母表示,对象类型则使用L加对象的全限定名表示。为了压缩字节码文件的体积,对于基本数据类型,jvm只使用一个大写字母来表示
B -byte C -char D -double F -float I -int J -long S short Z -boolean V -void L -对象类型,String类表示为Ljava/lang/String;
对于数组类型来说,每一个维度使用前置的[表示,如int[]被记录为[I,String[][]被记录为[[Ljava/lang/String;
用描述符描述方法时,按照先参数列表,后返回值的顺序来描述。参数列表按照参数的严格顺序放在一组()之内,如:String getName(int i, String j)的描述符为:(I,Ljava/long/String)Ljava/lang/String;
5. 访问标志(2个字节) 权限修饰符
6. 当前类名(2字节)
7. 父类名(2字节)
8. 接口信息(2+n个字节)
9. 字段信息(2+n个字节)
10. 方法信息(2+n个字节)
11. 属性信息(2+n个字节)