首页 > 代码库 > JAVA垃圾回收机制
JAVA垃圾回收机制
java中提供了垃圾回收器(简称gc),对于不再使用的内存能自动将其释放。那gc是怎么工作的呢?
居然要垃圾回收,那么就要定位什么是“垃圾”。在JAVA里面认为对任何“活”的对象,都能追溯到其在堆栈区或静态存储区的引用,简称“活对象”,简单点来说就是有对象引用指向它。那么怎么找出所有的“活对象”呢?就是从堆栈和静态存储区出发遍历所有的对象引用,定位引用指向的对象,该对象中包含的所有对象引用,如此反复进行就找出了所有的活对象。其余的就被当作垃圾处理。
垃圾回收一般有两种方式,一是“停止-复制”,二是“标记-清扫”。
“停止-复制”,就是停止当前运行的程序,把当前所有“活对象”从当前堆复制到另一个堆,然后修正对象引用。这个方法有个好处就是新堆里的对象排列紧凑,有利于分配新的内存。但缺点也很明显,那就是动作太大,需要多一倍的空间。另外对于运行稳定的程序,只会产生很少的垃圾,用这种方式就很浪费。
“标记-清扫”,就是对于所有的活对象,给它一个标记,未标记的则被释放。这个缺点就是清扫后的堆空间不连续的,但是它在只产生少量垃圾的时候效率很高。
可以看出上面的两种方式是互补的,所以java虚拟机gc的工作是自适应的。也就是说Jvm会对其进行跟踪,如果所有对象都很稳定,gc工作效率降低就转换到“标记-清扫”方式,如果堆空间出现很多碎片,就会切换到“停止-复制”方式。另外,jvm内存分配方式是以“块”为单位的,较大的对象会单独占有块。大型对象仍然不会被复制,内含小型对象的则会被复制并整理。
一个很重要的问题就是gc只会释放那些用new分配的内存,当JIN时,比如说调用了C语言,那么C用malloc分配的内存就无能为力了。这时fanalize()就出现了,它的工作原理是这样的:一旦垃圾回收机制准备好释放某个对象占用的内存控件时,将会首先调用finalize()方法,当垃圾回收发生时,就会真正回收对象占有的内存。所以用finalize()方法就可以在垃圾回收时刻做一些重要的清理工作。垃圾回收只跟内存有关,所以finalize()的清理也应该只跟内存有关。
但是垃圾回收机制也是需要资源的,所以不是必要时刻(濒临存储空间用完),垃圾回收不会发生。也就是说finalize()方法并不会保证被调用。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。