皮皮网

皮皮网

【传奇竞技源码】【mc启动源码】【游资进入源码】weakreference源码

时间:2024-11-19 01:45:14 分类:焦点

1.java三个引用类型
2.Andorid进阶一:LeakCanary源码分析,从头到尾搞个明白
3.Java中弱引用 丨 12分钟通过案例带你深入源码,分析其原理

weakreference源码

java三个引用类型

       å››ç§å¼•ç”¨ç±»åž‹

       æ‰€ä»¥åœ¨ JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

       ä¸€ï¼Œå¼ºå¼•ç”¨

       Java中默认声明的就是强引用,比如:

       Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收

       obj = null; //手动置null

       åªè¦å¼ºå¼•ç”¨å­˜åœ¨ï¼Œåžƒåœ¾å›žæ”¶å™¨å°†æ°¸è¿œä¸ä¼šå›žæ”¶è¢«å¼•ç”¨çš„对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了

       äºŒï¼Œè½¯å¼•ç”¨

       è½¯å¼•ç”¨æ˜¯ç”¨æ¥æè¿°ä¸€äº›éžå¿…需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。

       åœ¨ JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。

       ä¸‹é¢ä»¥ä¸€ä¸ªä¾‹å­æ¥è¿›ä¸€æ­¥è¯´æ˜Žå¼ºå¼•ç”¨å’Œè½¯å¼•ç”¨çš„区别:

       åœ¨è¿è¡Œä¸‹é¢çš„Java代码之前,需要先配置参数 -Xms2M -Xmx3M,将 JVM 的初始内存设为2M,最大可用内存为 3M。

       é¦–先先来测试一下强引用,在限制了 JVM 内存的前提下,下面的代码运行正常

       public class TestOOM {

        public static void main(String[] args) {

        testStrongReference();

        }

        private static void testStrongReference() {

        // 当 new byte为 1M 时,程序运行正常

        byte[] buff = new byte[ * * 1];

        }

       }

       ä½†æ˜¯å¦‚果我们将

       byte[] buff = new byte[ * * 1];

       æ›¿æ¢ä¸ºåˆ›å»ºä¸€ä¸ªå¤§å°ä¸º 2M 的字节数组

       byte[] buff = new byte[ * * 2];

       åˆ™å†…存不够使用,程序直接报错,强引用并不会被回收

       æŽ¥ç€æ¥çœ‹ä¸€ä¸‹è½¯å¼•ç”¨ä¼šæœ‰ä»€ä¹ˆä¸ä¸€æ ·ï¼Œåœ¨ä¸‹é¢çš„示例中连续创建了 个大小为 1M 的字节数组,并赋值给了软引用,然后循环遍历将这些对象打印出来。

       public class TestOOM {

        private static List<Object> list = new ArrayList<>();

        public static void main(String[] args) {

        testSoftReference();

        }

        private static void testSoftReference() {

        for (int i = 0; i < ; i++) {

        byte[] buff = new byte[ * ];

        SoftReference<byte[]> sr = new SoftReference<>(buff);

        list.add(sr);

        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){

        Object obj = ((SoftReference) list.get(i)).get();

        System.out.println(obj);

        }

        }

       }

       æ‰“印结果:

       æˆ‘们发现无论循环创建多少个软引用对象,打印结果总是只有最后一个对象被保留,其他的obj全都被置空回收了。

       è¿™é‡Œå°±è¯´æ˜Žäº†åœ¨å†…存不足的情况下,软引用将会被自动回收。

       å€¼å¾—注意的一点 , 即使有 byte[] buff 引用指向对象, 且 buff 是一个strong reference, 但是 SoftReference sr 指向的对象仍然被回收了,这是因为Java的编译器发现了在之后的代码中, buff 已经没有被使用了, 所以自动进行了优化。

       å¦‚果我们将上面示例稍微修改一下:

        private static void testSoftReference() {

        byte[] buff = null;

        for (int i = 0; i < ; i++) {

        buff = new byte[ * ];

        SoftReference<byte[]> sr = new SoftReference<>(buff);

        list.add(sr);

        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){

        Object obj = ((SoftReference) list.get(i)).get();

        System.out.println(obj);

        }

        System.out.println("buff: " + buff.toString());

        }

       åˆ™ buff 会因为强引用的存在,而无法被垃圾回收,从而抛出OOM的错误。

       å¦‚果一个对象惟一剩下的引用是软引用,那么该对象是软可及的(softly reachable)。垃圾收集器并不像其收集弱可及的对象一样尽量地收集软可及的对象,相反,它只在真正 “需要” 内存时才收集软可及的对象。

       ä¸‰ï¼Œå¼±å¼•ç”¨

       å¼±å¼•ç”¨çš„引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

       æˆ‘们以与软引用同样的方式来测试一下弱引用:

        private static void testWeakReference() {

        for (int i = 0; i < ; i++) {

        byte[] buff = new byte[ * ];

        WeakReference<byte[]> sr = new WeakReference<>(buff);

        list.add(sr);

        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){

        Object obj = ((WeakReference) list.get(i)).get();

        System.out.println(obj);

        }

        }

       æ‰“印结果:

       å¯ä»¥å‘现所有被弱引用关联的对象都被垃圾回收了。

       å››ï¼Œè™šå¼•ç”¨

       è™šå¼•ç”¨æ˜¯æœ€å¼±çš„一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,在 JDK1.2 之后,用 PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。

       public class PhantomReference<T> extends Reference<T> {

        /

**

        * Returns this reference object's referent. Because the referent of a

        * phantom reference is always inaccessible, this method always returns

        * <code>null</code>.

       

*

        * @return <code>null</code>

        */

        public T get() {

        return null;

        }

        public PhantomReference(T referent, ReferenceQueue<? super T> q) {

        super(referent, q);

        }

       }

       é‚£ä¹ˆä¼ å…¥å®ƒçš„构造方法中的 ReferenceQueue 又是如何使用的呢?

       äº”,引用队列(ReferenceQueue)

       å¼•ç”¨é˜Ÿåˆ—可以与软引用、弱引用以及虚引用一起配合使用,当垃圾回收器准备回收一个对象时,如果发现它还有引用,那么就会在回收对象之前,把这个引用加入到与之关联的引用队列中去。程序可以通过判断引用队列中是否已经加入了引用,来判断被引用的对象是否将要被垃圾回收,这样就可以在对象被回收之前采取一些必要的措施。

Andorid进阶一:LeakCanary源码分析,从头到尾搞个明白

       内存优化掌握了吗?知道如何定位内存问题吗?面试官和蔼地问有些拘谨的小张。小张回答道:“就是用LeakCanary检测一下泄漏,找到对应泄漏的传奇竞技源码地方,修改错误的代码,回收没回收的引用,优化生命周期线程的依赖关系。”“那你了解LeakCanary分析内存泄漏的原理吗?”面试官追问。“不好意思,平时没有注意过。”小张心想:面试怎么总问这个,我只是mc启动源码一个普通的程序员。

       前言:

       应用性能优化是开发中不可或缺的一环,而内存优化尤为重要。内存泄漏导致的内存溢出崩溃和内存抖动带来的卡顿不流畅,都在切实影响着用户体验。LeakCanary常用于定位内存泄漏问题,是时候深入理解它的工作机制了。

       名词理解:

       hprof:hprof文件是Java的内存快照文件,格式后缀为.hprof,在LeakCanary中用于内存分析。WeakReference:弱引用,当对象仅被weak reference指向,没有任何其他strong reference指向时,在GC运行时,游资进入源码这个对象就会被回收,不论当前内存空间是否足够。在LeakCanary中用于监测被回收的无用对象是否被释放。Curtains:Square的另一个开源框架,用于处理Android窗口的集中式API,在LeakCanary中用于监测window rootView在detach后的内存泄漏。

       目录:

       本文将从以下几个方面进行分析:

       一,怎么用?

       查看官网文档可以看出,使用LeakCanary非常简单,只需添加相关依赖即可。debugImplementation只在debug模式的编译和最终的debug apk打包时有效。LeakCanary的初始化代码通过ContentProvider进行,会在AppWatcherInstaller类的京客源码oncreate方法中调用真正的初始化代码AppWatcher.manualInstall(application)。在AndroidManifest.xml中注册该provider,注册的ContentProvider会在application启动的时候自动回调oncreate方法。

       二,官方阐述

       安装LeakCanary后,它会通过4个步骤自动检测并报告内存泄漏:如果ObjectWatcher在等待5秒并运行垃圾收集后没有清除持有的弱引用,则被监视的对象被认为是保留的,并且可能会泄漏。LeakCanary会将其记录到Logcat中,并在泄漏列表展示中用Library Leak标签标记。LeakCanary附带一个已知泄漏的数据库,通过引用名称的模式匹配来识别泄漏,如Library Leaks。对于无法识别的源码论坛技术泄漏,可以报告并自定义已知库泄漏的列表。

       三,监测activity,fragment,rootView和viewmodel

       初始化的代码关键在于AppWatcher作为Android平台使用ObjectWatcher封装的API中心,自动安装配置默认的监听。我们分析了四个默认监听的Watcher,包括ActivityWatcher,FragmentAndViewModelWatcher,RootViewWatcher和ServiceWatcher,分别用于监测activity,fragment,rootView和service的内存泄漏。

       四,ObjectWatcher保留对象检查分析

       LeakCanary通过ObjectWatcher监控内存泄漏,我们深入分析了其检查过程,包括创建弱引用,检查对应key对象的保留,以及内存快照转储和内存分析。

       五,总结

       本文全面分析了LeakCanary的实现原理,从安装、使用到内存泄漏的检测和分析,详细介绍了各个组件的作用和工作流程。通过深入理解LeakCanary,开发者可以更有效地定位和解决内存泄漏问题,优化应用性能。阅读源码不仅能深入了解LeakCanary的工作机制,还能学习到内存泄漏检测的通用方法和技巧。

Java中弱引用 丨 分钟通过案例带你深入源码,分析其原理

       深入理解Java中的弱引用:分钟带你探索原理与应用

       弱引用在Java中扮演着微妙的角色,它并非阻止垃圾回收,而是提供了一种特殊关联方式。JDK官方解释,弱引用主要用于实现那些不需要阻止其键或值被回收的映射。弱引用的出现,是为了在不再使用对象时,让垃圾回收器在合适的时候自动回收,从而避免内存溢出问题。

       让我们通过实例来了解。想象一个场景,当我们维护一个map,存储了大量生命周期短暂的对象,如果key和value都由强引用指向,即使我们设置为null,对象仍不会被回收,因为map作为静态变量,其生命周期长。这时,弱引用的介入就显得尤为重要。通过将key变为弱引用,即使对象不再被方法引用,也能在垃圾回收时被释放,避免内存耗尽。

       弱引用的使用并不复杂,只需将HashMap替换为WeakHashMap,将key变为WeakReference。当我们不再需要这些对象时,它们会被自动回收,如在上述例子中,输出的size为0,就证明了这一点。然而,这并不意味着value和entry会自动回收,这时WeakHashMap的expungeStaleEntries方法就发挥作用,它会清理不再引用的对象。

       引用队列在此过程中扮演了关键角色,它帮助我们在弱引用被回收时高效地找到并处理相关对象,避免了遍历整个数据结构的性能消耗。在使用弱引用时,需要注意检查对象是否已被回收,以防空指针异常。

       通过这些深入解析,我们对弱引用有了全面的认识,它在内存管理中的巧妙应用,为我们提供了一种解决内存溢出的有效手段。