java加快内存回收_Java提高——Java的内存回收(1)

Java引用的种类

当程序员通过new关键字创建对象,即视为为Java对象申请内存空间。JVM会在堆内存中为每个对象分配空间;当一个对象失去引用的时候,JVM垃圾回收机制会自动清除他们,并回收他们所占用的内存空间。

Java内存管理包括内存分配(创建Java对象的时候)和内存回收(回收 Java对象的时候)两个方面。

JVM垃圾回收机制是否回收一个对象的标准:是否有引用变量引用该对象?

classNod{

Nod next;String name;publicNod(String name) {

this.name= name;}

}

public classNodeTest {

public static voidmain(String[] args) {

Nod n1 = newNod("第一个节点");Nod n2 = newNod("第二个节点");Nod n3 = newNod("第三个节点");n1.next= n2;n2 = null;n3 = n2;}

}

JVM的垃圾回收机制采用有向图的方式来管理内存中的对象。程序的有向图:

fb70286d6689b1cda733dc69490c20bb.png

有向图现实只有“节点3”处于不可达状态,因此JVM的垃圾回收机制将会回收它。

对象在堆内存中对应的有向图的状态:可达状态、可恢复状态、不可达状态

bd58952c93e87158a94e538f18dfcaa3.png

Java语言对对象的引用方式:强引用、软引用、弱引用、虚引用

强引用:程序创建一个对象,并将对象赋给一个引用变量,这就是强引用。当对象被一个及以上的强引用变量引用时,它处于可达状态,不可被垃圾回收机制回收。处于强引用的对象绝对不会被垃圾回收机制回收,即使内存紧张。由于JVM不会回收强引用所引用的Java对象,因此强引用是造成内存泄漏的主要原因。

软引用:当一个对象只有软引用的时候,可能会被垃圾回收机制回收——当系统内存空间足够的时候不会回收,系统内存空间不足的时候会回收。软引用常用于对内存敏感的程序中。

classPerson{

intage;String name;publicPerson( String name,intage) {

this.age= age;this.name= name;}

@OverridepublicString toString() {

return"Person{"+

"age="+ age+

", name='"+ name+ '\''+

'}';}

}

public classSoftReferenceTest {

public static voidmain(String[] args) {

SoftReference[] person = newSoftReference[100];for(inti = 0;i < person.length;i++) {

person[i] = newSoftReference(newPerson("名字"+i,(i+1)*4%100));}

System.out.println(person[2].get());System.out.println(person[4].get());//通知系统进行垃圾回收System.gc();System.runFinalization();//强制调用已经失去引用的对象的finalize方法//垃圾回收机制运行后,SoftReference的元素数组保持不变System.out.println(person[2].get());System.out.println(person[4].get());}

}

d96628fdec0d12c5988f29c0fd9e5037.png

弱引用:弱引用与软引用类似,区别在于弱引用所引用对象的生存期更短。弱引用的级别更低。对于弱引用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。

public classWeakReferenceTest {

public static voidmain(String[] args) {

//创建字符串对象String str = newString("java");//创建WeakReference对象WeakReference weakReference = newWeakReference(str);//切断weakReference和java对象之间的引用str = null;//取出弱引用所引用的对象System.out.println(weakReference.get());//强制垃圾回收System.gc();System.runFinalization();//再次取出弱引用所引用的对象System.out.println(weakReference.get());}

}

53a9c8568380f16213080540a2190303.png

e99c6c70d7a7cbd381754390be1f8e7e.png

弱引用具有很大的不确定性,因为每次回收机制执行的时候都会回收弱引用对象,而垃圾回收机制又不受程序员控制,因此程序获取弱引用的Java对象时,必须小心空指针异常——通过弱引用获取的Java对象可能为null。

与WeakReference功能类似的还有WeakHashMap,当有大量Java对象需要使用弱引用时,可以考虑WeakHashMap

classCrazyKey{

String name;publicCrazyKey(String name) {

this.name= name;}

@Overridepublic booleanequals(Object o) {

if(this== o) return true;if(o == null|| getClass() != o.getClass()) return false;CrazyKey crazyKey = (CrazyKey) o;returnObjects.equals(name,crazyKey.name);}

@Overridepublic inthashCode() {

returnObjects.hash(name);}

@OverridepublicString toString() {

return"CrazyKey{"+

"name='"+ name+ '\''+

'}';}

}

public classWeakHashMapTest {

public static voidmain(String[] args) throwsInterruptedException {

WeakHashMap weakHashMap = newWeakHashMap();//循坏放入10个key-valuefor(inti = 0;i < 10;i++) {

weakHashMap.put(newCrazyKey(i+1+""),"value"+(i+1));}

//垃圾回收之前weakHashMap与普通的hashMap没有什么区别System.out.println(weakHashMap);System.out.println(weakHashMap.get(newCrazyKey("2")));//垃圾回收System.gc();//让线程休眠Thread.sleep(50);//垃圾回收后weakHashMap里的所有内容被清空System.out.println(weakHashMap);System.out.println(weakHashMap.get(newCrazyKey("2")));}

}

虚引用:软引用和弱引用可以单独使用,虚引用不能单独使用,必须和引用队列联合使用,虚引用的主要作用就是跟踪对象被垃圾回收的状态。程序可以通过检查与虚引用关联的引用队列中是否包含指定的虚引用,从而了解虚引用所引用的对象是否被回收。

引用队列由java.lang.ref.ReferenceQueue类表示,用于保存被回收后对象的引用,当把软引用、弱引用和引用队列联合使用的时候,系统回收被引用的对象之后,将会把被回收的对象的引用添加到关联的引用队列之中。与软引用和弱引用不同的是,虚引用在对象被释放之前放进了队列之中,这使得可以在对象被回收之前采取行动。

public classPhantomReferenceTest {

public static voidmain(String[] args) {

//字符串对象String str = newString("java");//创建引用队列对象ReferenceQueue rq = newReferenceQueue();//创建虚引用对象,让虚引用引用“java”对象PhantomReference pr = newPhantomReference(str,rq);//切断str和“java”的引用关系str =null;//试图取出虚引用所引用的对象,但程序并不能通过虚引用访问被引用的对象,因此为nullSystem.out.println(pr.get());//强制垃圾回收System.gc();System.runFinalization();//取出引用队列中最先进入队列中引用与pr进行比较System.out.println(rq.poll() == pr);}

}

c917105ecca459ef5fbd233aeed48199.png

要使用这些特殊的引用类,就不能保留对对象的强引用。否则就会浪费这些引用所带来的好处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java内存泄漏和内存溢出是两个不同的问题。内存泄漏是指程序在申请内存后,无法释放已申请的内存空间,导致内存不断被占用,最终导致内存耗尽。而内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,导致无法分配所需的内存空间。 Java内存泄漏通常是由于程序中存在未释放的对象引用导致的。比如一个对象占用了一定的内存空间,但是在使用完后没有及时释放,导致这部分内存无法被回收。如果这种内存泄漏发生多次,最终会导致内存耗尽。 Java内存溢出则是由于程序需要申请的内存超过了JVM可用的内存空间。当程序申请的内存超过了JVM可用的内存空间时,就会发生内存溢出的问题。这通常是由于程序中创建了过多的对象或者申请了过大的内存空间导致的。 总结来说,Java内存泄漏是指程序无法释放已申请的内存空间,导致内存不断被占用,而内存溢出是指程序需要申请的内存超过了JVM可用的内存空间。 #### 引用[.reference_title] - *1* *2* [JAVA内存溢出和内存泄漏](https://blog.csdn.net/weixin_39555954/article/details/126689450)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Java基础恶补——内存泄露、内存溢出](https://blog.csdn.net/wisgood/article/details/16818243)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值