行业知识
JAVA 内存泄漏相关知识学习
1 强引用
强引���回收机制
强引用需要切断引用关系,才可以让对象被垃圾回收器正常回收
示例:
@Test fun testMemoryLeak(){ var m:M? = M() System.gc() println("打印m对象 == $m") m = null System.gc() println("置空之后打印m == $m") } 结果:
打印m对象 == com.example.testdemo2.M@6f53b8a
置空之后打印m == null
该对象被回收了finalize
2 弱引用
弱引用的回收机制
弱引用只要java触发gc垃圾回收,被弱引用持有的对象就会被回收掉。
示例:
@Test fun testWeakReference(){ val ref = WeakReference(Person()) println("打印弱引用持有的对象 == ${ref.get()}") Thread.sleep(5000) println("打印弱引用持有的对象 == ${ref.get()}") Thread.sleep(5000) System.gc() println("GC之后打印弱引用持有的对象 == ${ref.get()}") } class Person{ var name = "zhangsan" } 结果:
打印弱引用持有的对象 == com.example.testdemo2.ExampleUnitTest$Person@6b695b06
打印弱引用持有的对象 == com.example.testdemo2.ExampleUnitTest$Person@6b695b06
GC之后打印弱引用持有的对象 == null
3 软引用
软引用回收机制
软引用会在jvm分配内存不足的时候,释放回收其引用的对象,在触发gc时,只要内存分配足够,是不会被回收的,只有到使用内存大于分配内存的时候才会回收该对象的引用。
示例
@Test fun testSoftReference() { val softRef = SoftReference(ByteArray(1024 * 1024 * 10)) println("打印软引用 == ${softRef.get()}") System.gc() Thread.sleep(500) println("打印软引用 == ${softRef.get()}") val softRef2 = SoftReference(ByteArray(1024 * 1024 * 12)) println("打印软引用 == ${softRef.get()}") } 结果:
jvm分配空间为20M的情况下,就会造成软引用中的对象被回收掉
打印软引用 == [B@58a9760d
打印软引用 == [B@58a9760d
打印软引用 == null
4 ThreadLocal的使用
ThreadLocal 自带线程隔离机制,因为ThreadLocal在设置对象的时候,会用当前的线程作为key存储当前设置的引用对象,所以每个线程中只能获取到自己存放的引用对象,无法获取其他线程中存储的值,从而起到的线程隔离的作用。
示例
@Test fun testThreadLocal(){ val threadLocal = ThreadLocal() Thread{ threadLocal.set(Person()) println("线程1 == 打印threadLocal中的存储的信息 == ${threadLocal.get()}") threadLocal.remove() println("线程11 == 打印threadLocal中的存储的信息 == ${threadLocal.get()}") }.start() Thread{ println("线程2 == 打印threadLocal中的存储的信息 == ${threadLocal.get()}") }.start() } class Person{ var name = "zhangsan" } 结果
线程2 == 打印threadLocal中的存储的信息 == null
线程1 == 打印threadLocal中的存储的信息 == com.benben.TestDataDemo.TestDataDemoApplicationTests$Person@6388e817
线程11 == 打印threadLocal中的存储的信息 == null
从结果上看 只有线程1的日志中正常拿到了设置进去的Person对象,线程11之所以没有拿到 是因为当前线程中的threadLocal对象已经将存储的信息进行了remove,线程2拿不到的原因是因为不在同一个线程中,即使使用同一个threadLocal对象也无法获取相同的map容器,所以获取存储对象的时候拿到了null