Java虚拟机进阶

博客介绍了Java中内存泄漏的情况,如使用静态集合类、单例模式、未关闭资源等,并给出解决办法。还阐述了类的实例化顺序,遵循先静态、先父后子、先成员后构造原则。此外,讲解了GC回收策略,包括不可达检测、引用计数为0,以及四种类型的引用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么时候会发生内存泄漏:

(1)使用静态的集合类

public static List...

静态的集合类的生命周期和应用程序的生命周期一样长,所以在程序结束前容器中的对象不能被释放,会造成内存泄露。

解决办法是最好不使用静态的集合类,如果使用的话,在不需要容器时要将其赋值为null。

(2)单例模式可能会造成内存泄露

单例模式只允许应用程序存在一个实例对象,并且这个实例对象的生命周期和应用程序的生命周期一样长,如果单例对象中拥有另一个对象的引用的话,这个被引用的对象就不能被及时回收。

解决办法是单例对象中持有的其他对象使用弱引用,弱引用对象在GC线程工作时,其占用的内存会被回收掉。

(3)数据库、网络、输入输出流,这些资源没有显示的关闭

    垃圾回收只负责内存回收,如果对象正在使用资源的话,Java虚拟机不能判断这些对象是不是正在进行操作,比如输入输出,也就不能回收这些对象占用的内存,所以在资源使用完后要调用close()方法关闭。

类的实例化顺序

(1) 类中的static代码在类加载时就执行,且只执行这一次。(先静态)

(2)如果一个类A继承了类B,在类A实例化时要先加载类B,在执行类A的构造函数时要先执行父类B的构造函数,所以此时要实例化类B。(先父后子)

(3)一个类实例化之前要先实例化类的成员变量(非静态),再执行该类的构造函数。(先成员后构造)

GC回收策略

JVM回收的对象,是那些已经不再被使用的对象。而判断是否不再被使用的原则,可以从两个方面来描述。第一是不可到达,第二是引用计数为0。这两点,其实说的是一回事,从不同的方面来描述罢了。

不可达检测

从GC Root出发,对象之间的引用链没有指向的对象,我们称之为不可到达。

引用计数为0

引用计数为0其实说的就是从GC Root开始的对象引用链到达该对象的引用计数为0,即没有可到达的引用路径指向它了。

在Java语言中,可以作为GC Roots的对象包括下面几种:

(1)虚拟机栈中引用的对象。

(2)方法区中静态属性引用的对象。

(3)方法区中常量引用的对象。

(4)本地方法栈中本地方法引用的对象。

四种类型的引用

强引用:使用最普遍的引用:Object o=new Object(); 特点:不会被GC。将对象的引用显示地置为null:o=null; (帮助垃圾收集器回收此对象)

软引用:用来描述一些还有用但是并非必须的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。

弱引用:与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象(前提是此对象不再被其他外部对象引用),不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象。

ThreadLocalMap 使用弱引用的目的:当 threadLocal 实例可以被GC回收时,系统可以检测到该 threadLocal 对应的Entry是否已经过期(根据reference.get() == null来判断,如果为true则表示过期,程序内部称为stale slots)来自动做一些清除工作,否则如果不清除的话容易产生内存无法释放的问题——value对应的对象即使不再使用,但由于被threadLocalMap所引用导致无法被GC回收。

虚引用(幻影引用):一个对象是否有虚引用的存在完全不会对其生存时间构成影响,也无法通过虚引用来获取一个对象的真实引用。唯一的用处:能在对象被GC时收到系统通知,JAVA中用PhantomReference来实现虚引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值