做自媒体都有什么网站,下载黑龙江建设网官网网站,提供网站建设方案,宁波专业的网站建设1.如何判断对象是否存活 1.1 引用计数算法 概念#xff1a;在对象头部增加一个引用计数器,每当有一个地方引用它时#xff0c;计数器值就加一#xff1b;当引用失效时#xff0c;计数器值就减一#xff1b;任何时刻计数器为零的对象就是不可能再被使用的。 优点#xff1…1.如何判断对象是否存活 1.1 引用计数算法 概念在对象头部增加一个引用计数器,每当有一个地方引用它时计数器值就加一当引用失效时计数器值就减一任何时刻计数器为零的对象就是不可能再被使用的。 优点速度快高效 缺点 假如此时A引用BB引用A那么计数永远不为0那么永远无法回收他们 1.2 可达性分析算法 概念通过一系列称为“GC Roots”的根对象作为起始节点集从这些节点开始根据引用关系向下搜索搜索过程所走过的路径称为“引用链”Reference Chain如果某个对象到GC Roots间没有任何引用链相连或者用图论的话来说就是从GC Roots到这个对象不可达时则证明此对象是不可能再被使用的。 总结概念: 也就是找到是否连接根节点此时如果A引用BB引用A就不会发生,循环回收不掉的问题因为他们找不到连接的根节点,也是当前主流的判断对象是否存活的算法 注意即使在可达性分析算法中判定为不可达的对象也不是“非死不可”的这时候它们暂时还处于“缓刑”阶段要真正宣告一个对象死亡至少要经历两次标记过程如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链那它将会被第一次标记随后进行一次筛选筛选的条件是此对象是否有必要执行finalize()方法。 2.再谈引用 无论是通过引用计数算法判断对象的引用数量还是通过可达性分析算法判断对象是否引用链可 达判定对象是否存活都和“ 引用 ” 离不开关系。 在JDK 1.2 版之前 Java 里面的引用是很传统的定义 如果reference 类型的数据中存储的数值代表的是另外一块内存的起始地址就称该 reference 数据是代表 某块内存、某个对象的引用。这种定义并没有什么不对只是现在看来有些过于狭隘了一个对象在 这种定义下只有“ 被引用 ” 或者 “ 未被引用 ” 两种状态对于描述一些 “ 食之无味弃之可惜 ” 的对象就显 得无能为力。 譬如我们希望能描述一类对象当内存空间还足够时能保留在内存之中如果内存空 间在进行垃圾收集后仍然非常紧张那就可以抛弃这些对象 —— 很多系统的缓存功能都符合这样的应用场景。 所以在JDK 1.2版之后Java对引用的概念进行了扩充,引入了四种引用 3.四种引用 2.1 强引用 是最传统的“引用”的定义是指在程序代码之中普遍存在的引用赋值即类似“Object objnew Object()”这种引用关系。无论任何情况下只要强引用关系还存在垃圾收集器就永远不会回收掉被引用的对象。 2.2 软引用 是用来描述一些还有用但非必须的对象。只被软引用关联着的对象在系统将要发生内存溢出异常前会把这些对象列进回收范围之中进行第二次回收如果这次回收还没有足够的内存才会抛出内存溢出异常。在JDK 1.2版之后提供了SoftReference类来实现软引用。 2.3 弱引用 也是用来描述那些非必须对象但是它的强度比软引用更弱一些被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作无论当前内存是否足够都会回收掉只被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。 2.4 虚引用 也称为“幽灵引用”或者“幻影引用”它是最弱的一种引用关系。一个对象是否有虚引用的存在完全不会对其生存时间构成影响也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2版之后提供了PhantomReference类来实现虚引用。 3. 软引用的进一步了解 3.1 软引用的使用场景 软引用主要用于实现内存敏感的高速缓存。当系统内存充足时软引用的对象可以长时间驻留在内存中供程序快速访问当系统内存不足时这些对象可以被垃圾回收器回收从而避免内存溢出错误。这种机制非常适合用于缓存系统如图片缓存、页面缓存等。 3.2 为什么用到了软引用 内存压力下的灵活应对软引用允许JVM在内存紧张时自动回收对象从而避免了程序因为内存不足而崩溃的风险。 提高性能通过保留软引用对象在内存充足时可以直接访问这些对象减少了重新加载或重新计算这些对象所需的时间和资源。 资源管理的灵活性开发者可以通过软引用来控制缓存的大小和生命周期而不是完全依赖于JVM的垃圾回收机制。 3.3 软引用的使用(小例子) import java.lang.ref.SoftReference; public class SoftReferenceExample { public static void main(String[] args) { // 假设这是我们需要缓存的数据 Object data new Object(); // 创建一个软引用指向这个数据 SoftReferenceObject softRef new SoftReference(data); // 使用softRef.get()来获取软引用指向的对象 Object cachedData softRef.get(); // 模拟内存紧张的情况实际上在简单示例中无法直接模拟 // 在实际环境中当JVM进行垃圾回收时如果内存不足可能会回收softRef指向的对象 // 再次尝试获取对象如果对象已被回收则返回null cachedData softRef.get(); if (cachedData ! null) { // 对象仍然存在可以继续使用 } else { // 对象已被回收需要重新加载或重新计算 } }
} 注意由于垃圾回收的时机和过程是由JVM的垃圾回收器控制的因此我们不能精确地预测软引用对象何时会被回收。在实际应用中开发者需要根据应用的内存需求和性能要求来合理使用软引用。 4. 弱引用的进一步了解 4.1 使用场景 缓存系统 在一些缓存系统中特别是当缓存的数据量很大且不是必需时可以使用弱引用来引用这些数据。这样当JVM内存不足时这些数据可以被自动回收从而避免内存溢出。例如WeakHashMap就是基于弱引用实现的它允许键值对中的键是弱引用的。这意味着如果某个键除了被WeakHashMap所引用外没有其他强引用指向它那么这个键以及它所对应的值都可能被垃圾回收器回收。生命周期较短的临时对象 对于那些生命周期较短且对内存敏感的临时对象可以使用弱引用来引用它们。这样一旦这些对象不再被其他强引用所指向它们就可以被垃圾回收器及时回收。 4.2 为什么用到了弱引用 内存管理的灵活性 弱引用提供了一种比软引用更加灵活的内存管理方式。通过弱引用开发者可以更加精确地控制对象的生命周期避免内存泄漏同时也能够确保在内存不足时能够自动回收非必需的对象。减少内存泄漏的风险 在一些复杂的应用程序中由于对象之间的引用关系错综复杂很容易出现内存泄漏的情况。通过使用弱引用可以减少因为对象之间的强引用关系而导致的内存泄漏风险。提升性能 在一些性能敏感的应用程序中及时回收不再使用的对象可以释放更多的内存空间从而提升应用程序的性能。弱引用通过自动回收非必需的对象有助于减少内存占用提升性能。 4.3 弱引用的使用(小例子) import java.lang.ref.WeakReference; public class WeakReferenceExample { public static void main(String[] args) { // 创建一个强引用对象 Object strongRef new Object(); // 创建一个弱引用对象指向强引用对象 WeakReferenceObject weakRef new WeakReference(strongRef); // 验证弱引用是否有效 System.out.println(weakRef.get()); // 输出对象地址 // 将强引用置为null模拟对象不再被强引用 strongRef null; // 触发垃圾回收注意实际环境中垃圾回收的时机是不确定的 System.gc(); // 再次验证弱引用是否有效 // 由于强引用已被置为null且没有其他强引用指向该对象因此该对象可能会被垃圾回收 // 此时weakRef.get()可能返回null System.out.println(weakRef.get()); // 可能输出null }
} 同样和弱引用相同由于垃圾回收的时机和过程是由JVM的垃圾回收器控制的因此我们不能精确地预测弱引用对象何时会被回收。在实际应用中开发者需要根据应用的内存需求和性能要求来合理使用弱引用。