首页 技术 正文
技术 2022年11月14日
0 收藏 319 点赞 4,656 浏览 1675 个字

众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作.

虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏.

反而,某程度上,当出现内存泄漏,Debug会变得难度更大.

所以,Java程序员,有必要去了解Java虚拟机对于内存的管理以及垃圾回收的机制.


Java虚拟机是如何判断一个对象可以回收?

当一个对象没有被任何其他所引用时,这个对象被Java虚拟机视为可回收.

早起的虚拟机,使用引用计数的方法判断对象是否可回收.这个方法的好处是简单和效率高,却难以解决循环引用的问题.

现在主流的Java虚拟机都是使用可达性的分析对象是否可回收.从若干Root节点开始遍历,所有从Root节点能到达的对象,都是存活对象.

反之,其他对象就是可回收对象.可以想象,这是有若干个根节点的图,用图论术语就是判断每个节点的可达性.

强引用,软引用,弱引用,虚引用都是什么?

强引用Strong Reference就是平时最常见的,不加任何修饰的对象实例化,得到的都是强引用.

软引用Soft Reference,软引用的对象,当Java虚拟机垃圾回收时出现空间不足的情况,软引用的对象就会被回收.

弱引用Weak Reference,弱引用的对象,当Java虚拟机下一次垃圾回收时,无论如何都会被回收.

虚引用Phantom Reference,虚引用的对象任何一个时刻都不能取得其对象的实例.虚引用的使用在于跟踪对象的生死存亡,当虚引用被垃圾回收时,会收到一个系统通知.

垃圾回收算法都有哪些?

1.标记清除,顾名思义就是标记和清除两个阶段.这个算法的致命弱点是,会产生大量的内存碎片,导致后期即使有足够的内存空间也无法分配大的连续的内存空间.

2.复制算法,是把内存空间分成大小相等的两个区域,每次只使用其中一个区域.每次内存回收,都会把存活的对象复制到另外一个区域.

这个算法虽然解决了内存碎片的问题,但是是以内存缩小原来的一半为代价.

复制算法也常用在新生代的垃圾回收.因为大多数的对象都是朝生夕死的,不会存活过下一轮的垃圾回收.所以实际上并没有必要按照1:1的比例来划分内存空间.

现实情况,内存被划分为一个较大的eden区和两个较小的survivor区.HotSpot虚拟机的eden:survivor:survivor=8:1:1.

每次都会使用eden和其中一个survivor用来分配内存,当垃圾回收时会把存活的对象复制到另外一个survivor区.

当出现survivor的内存不足时,会动用老年代的内存空间.老年代起的是一个担保的作用.

3.标记整理算法.把存活的对象都标记出来,再移动到内存空间的一端,把端边界以外的内存空间都清除释放.老年代一般采用标记整理算法.

4.分代收集算法.一般把内存空间分成老年代和新生代,不同的区域根据对象存活的周期和特点,使用合适的垃圾回收算法.

新生代使用复制算法.老年代使用标记清除或者标记整理算法.

Java程序会在什么时候执行垃圾回收呢?

答案是,安全区域(Safe Region),指在一端代码片段之中,引用关系不会发生变化,在这个区域任意地方开始垃圾回收都是安全的.

当线程执行到安全区域时,会首先标识自己已经进入了安全区域.

当线程要离开安全区域时,它要检查系统是否已经完成了根节点枚举(或整个垃圾回收过程),如果完成那线程就继续执行,否则必须等到可以离开安全区域的信号为止.

让所有执行线程都停顿下来到达最近的安全区域,有两种方案:

1.抢占式中断(Preemptive Suspension).在垃圾回收发生时,首先把所有线程都全部中断,没有到达安全区域的线程,就恢复线程让它运行到最近的安全区域上.

现在,几乎没有Java虚拟机是使用抢占式中断,来暂停所有线程从而执行垃圾回收.

2.主动式中断(Voluntary Suspension).当准备执行垃圾回收时,会设置一个标志位,表示要开始垃圾回收了.所有线程都会在安全区域处轮询这个标志位.

当发现这个标志位被设置后,线程会暂停自己.

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,082
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,557
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,406
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,179
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,815
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898