Java之 对象引用

2021-08-30  本文已影响0人  五月笙

内存管理

Java的内存管理就是内存空间的分配和释放的过程。

示例一

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        for (int i = 0; i < 10000000; i++) {
            MyMemory myMemory = new MyMemory(this);
            myMemory.addCotent("添加内容 + " + i);
        }
    }

    public String addString(String text) {
        return "从外面的Main 添加数据 ==" + text;
    }

    public static class MyMemory {
        String text = "";
        MainActivity main;

        MyMemory(MainActivity main) {
            text = text + "1111";
            this.main = main;
        }

        public void addCotent(String add) {
            text = text + add;
            main.addString(text);
        }
    }
}

示例二

public class MemoryLeakTest {

    public static void main(String[] args) {
        Vector v = new Vector(100000000);
        for(int i=0;i<v.size();i++){
            Object o = new Object();
            v.add(o);
            o = null;
        }
    }

说明

在for循环中,循环申请Object对象,每申请一个放入Vector中,然后把Object对象置空。此时,对于Object对象来说,与GC Roots是有通路的,因为由Vector对象引用,但在Object对象置空后,Object对象又没有用途了,所以对于所有的Object对象来说,与GC Roots有通路,但是又没有用,所以造成了堆内存泄露。

什么是GC Roots?

什么是通路

ThreadLocal中,获取到线程私有对象是通过线程持有的一个threadLocalMap,然后传入ThreadLocal当做key获取到对象的,这时候就有个问题,如果你在使用完ThreadLocal之后,将其置为null,这时候这个对象并不能被回收,因为他还有 ThreadLocalMap->entry->key的引用,直到该线程被销毁,但是这个线程很可能会被放到线程池中不会被销毁,这就产生了内存泄露。

jdk是通过弱引用来解决的这个问题的,entry中对key的引用是弱引用,当你取消了ThreadLocal的强引用之后,他就只剩下一个弱引用了,所以也会被回收。

引用与回收

引用

不同的引用类型,主要体现的是对象不同的可达性(reachable)状态和对垃圾收集的影响。

Object o = new Object();
Object o = new Object();
SoftReference sr = new SoftReference(prev);
if(sr.get() != null) {
    o1 = (Object)sr.get();
} else {
    o = new Object();
    sr = new SoftReference(o1);
}
Object o = new Object();
WeakReference sr = new WeakReference(prev);
if(sr.get() != null) {
    o1 = (Object)sr.get();
} else {
    o = new Object();
    sr = new WeakReference(o);
}

弱引用是说JVM认为内存不足是什么时候,如果不回收会发生什么问题?

可达性

reachable.png

判断对象可达性,是 JVM 垃圾收集器决定如何处理对象的一部考虑。

所有引用类型,都是抽象类 java.lang.ref.Reference 的子类。可以查看reference 的源码

public abstract class Reference<T> {
    private T referent;
    volatile ReferenceQueue<? super T> queue;
    Reference next;
    private transient Reference<T> discovered;
    private static Reference.Lock lock = new Reference.Lock(null);
    private static Reference<Object> pending = null;
// .............
// .............
    public T get() {
        return this.referent;
    }

    public void clear() {
        this.referent = null;
    }
}

参考

Java中的强引用,软引用,弱引用,虚引用有什么用?
java内存模型和内存分配
浅析java内存管理机制
第4讲 | 强引用、软引用、弱引用、幻象引用有什么区别
ava四种引用---强、软、弱、虚的知识点总结

上一篇下一篇

猜你喜欢

热点阅读