堆
Heap 堆:是 JVM 内存中最大的一块,由所有线程共享,由垃圾回收器管理的主要区域,堆中对象大部分都需要考虑线程安全的问题
存放哪些资源
- 对象实例:类初始化生成的对象,基本数据类型的数组也是对象实例,new 创建对象都使用堆内存
- 字符串常量池:
- 字符串常量池原本存放于方法区,JDK7 开始放置于堆中
- 字符串常量池存储的是 String 对象的直接引用或者对象,是一张 string table
- 静态变量:静态变量是有 static 修饰的变量,JDK8 时从方法区迁移至堆中
- 线程分配缓冲区 Thread Local Allocation Buffer:线程私有但不影响堆的共性,可以提升对象分配的效率
堆内存相关
设置堆内存指令:-Xmx Size
内存溢出:new 出对象,循环添加字符数据,当堆中没有内存空间可分配给实例,也无法再扩展时,就会抛出 OutOfMemoryError 异常
堆内存诊断工具:(控制台命令)
- jps:查看当前系统中有哪些 Java 进程
- jmap:查看堆内存占用情况
jhsdb jmap --heap --pid 进程id
- jconsole:图形界面的,多功能的监测工具,可以连续监测
堆的划分
在 Java7 中堆内会存在年轻代、老年代和方法区(永久代):
- Young 区被划分为三部分,Eden 区和两个大小严格相同的 Survivor 区。Survivor 区某一时刻只有其中一个是被使用的,另外一个留做垃圾回收时复制对象。在 Eden 区变满的时候,GC 就会将存活的对象移到空闲的 Survivor 区间中,根据 JVM 的策略,在经过几次垃圾回收后,仍然存活于 Survivor 的对象将被移动到 Tenured 区间
- Tenured 区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在 Young 复制转移一定的次数以后,对象就会被转移到 Tenured 区
- Perm 代主要保存 Class、ClassLoader、静态变量、常量、编译后的代码,在 Java7 中堆内方法区会受到 GC 的管理,但是触发GC的时机比较晚,内存管理效率不高
分代原因:不同对象的生命周期不同,70%-99% 的对象都是临时对象,优化 GC 性能
1 | public static void main(String[] args) { |