JVM运行时的内存块
- pc寄存器:(线程独有)保存线程运行的java方法地址
- Java 虚拟接栈(线程独有):用于存储线程的栈帧
- Java堆(全局共享):随着Java虚拟机的启动 创建 存储着所有对象的实例以及数组对象,而且内置gc(垃圾回收机制)
- 方法区:运行常量池
- 本地方法栈:线程独有。
在jvm中gc(垃圾回收机制)是Java立足点之一。垃圾自动回收可以让Java程序员减少与内存打交道,更专注于业务的开发与实现。
垃圾回收需要实现如下几点
- 什么对象可以回收‘
- 何时回收
- 怎么回收
关于垃圾回收的对象定义,主要有两种:
- 检查这个对象是否有引用
比如:a =new A(); 那么对象A是有引用的。但这种方式会出现死锁,就是有两个或者多个对象之间相互引用,但这些对象都是没用的。怎么办?
- 检查这个对象是否根部对象可达。
只有一个root,root与其他对象直接或间接关联,如果这个对象根部不可达,那么这个对象就“垃圾”
利用根部是否可达的方式没有死锁,是目前jvm gc的主流实现方式。当然未来的路还很长,说不定还有更好的算法实现呢?
何时回收?
垃圾对象的产生,一般都是周期回收。在回收垃圾的时候,停止运行的java程序
怎么回收?
- 标记-清理:先将视为垃圾的对象标记,然后进行清理,这样清理出来的空间是不连续的
- 复制:将内存分成两半,然后将有效的复制到另一半。这样整理出来的内存空间是连续的
- 标记-清理-整理:针对标记-清理加了优化,整理出连续的内存空间。
进一步优化:
总会有一些对象会一直存在如静态变量,线程池。。。这些“老不死”就没必要老是检查它们了,可以减少检查和清理的周期。于是就有了,新生代,老生代,永久代
- 新生代:新建的对象,这里一般是局部对象,使用过后很快消亡。经过几个周期之后,将升级为老生代,新生代的存活率10%左右
- 老生代:从新生代升级为的老生代,拥有更顽强的生命,所以垃圾清理的算法和周期都与新生代不同
- 永久代:永久代并不是不可能死亡,清理还是要的只不过周期很长而已。