JVM内存区域
直接内存:不是虚拟机运行时数据区域同NIO相关。(NIO:New Input/Output类)可以使用Native方法库直接分配堆外内存,通过存储在Java堆中的DirectByteBuffer对象作为对外内存来引用。
对象创建
创建对象(克隆,反序列化)仅仅 new 关键字
当jvm遇到new指令,首先检查这个指令参数是否能在常量池中定位到一个类的符号引用。并检查是否被加载。如果没有则加载
Java堆内存分配算法:指针碰撞适用场景(带compact过程的收集器如:serial parnew)
空闲列表:适用场景(CMS 基于 Mark-Sweep)
//由于内存分配频繁采取两种措施
1 对分配内存空间动作同步处理
2 把内存分配动作按照线程划分在不同空间(Thread Local Allocation Buffer)
分配完:jvm将分配的内存空间初始化为零值(except object header) object header:存放对象是哪个类的实例,怎样找到类的元数据,对象hashcode,对象GC分代年龄
执行<init>方法把对象按照程序员意愿初始化
对象头包括两部分信息 1 存储对象自身运行时数据
如表
存储内容 |
标志位 |
状态 |
对象hashcode,分代年龄 |
||
指向锁记录指针 |
||
指向重量级锁记录指针 |
||
Null,不需要记录信息 |
||
偏向线程ID,偏向时间戳 |
2 类型指针,指向类元数据的指针,来确定是哪个类的实例注:查找元数据信息并不一定要求经过对象本身
通过栈上的reference数据来操作对上的具体对象
访问方式: 1 使用句柄 2 直接指针
GC回收的内存空间 Java堆和方法区
垃圾收集器如何判定是否收集对象呢
1 引用计数法
给对象添加一个引用计数器,当有地方引用时,计数器值增加一,当引用失效,减一
弊端:很难解决对象相互引用
2 可达性分析法
1 设置GC Roots对象为起始点如果某个对象同GC Roots之间没有引用链则判定为可回收
GC Roots一般以下
虚拟机栈中引用对象方法区中静态属性引用对象方法区中常量引用对象本地方法栈JNI(Native方法)
四种引用
强引用(Strong Reference)
类似于Object obi = new Object();,无论内存空间够不够,GC都不会回收,而是抛出OOM
软引用(soft Reference)当内存不够,GC会回收软引用对象够则不会回收
弱引用(Weak Reference)只要GC执行,都会回收
虚引用(phantom Reference))对象被GC ,得到System notify
关于finalize()
1 假如对象同GC Roots没有引用链,jvm列入回收目标
2 通过了解此对象是否有必要执行finalize方法(假如对象没有override finalize method or the finalize method has been invoked)then it will not do finalize method
回收方法区
方法区主要两部分内容废弃常量和无用的类
废弃常量:没有任何对象引用常量池中相应的常量
无用的类:1 所有实例被回收 2 该类的ClassLoader被回收 3 该类对应的Class对象没有在任何地方被引用,无法通过反射访问该类方法
反射动态代理 CGLIB 动态生成JSP OSGI 频繁自定义ClassLoader都需要jvm的类卸载function
回收方法:1 标记清除算法不足容易产生碎片,出发GC
2 复制算法不足缩小了运行内存
3 标记整理算法
4分代收集算法