JVM系列之对象是否存活

2023-10-29

前言

之前我们讲过了JVM的内存区域和内存溢出,今天我们谈下处于JVM中的对象的问题,这些对象是否存活,如何判断,又如何去处理呢,带着这些疑问我们开启今天的JVM之旅。

 

如何判断对象是否存活?

  • 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就+1,当引用失效时,计数器的值就-1;当计数器的值为0时,就表示该对象为不可用对象;

    优点:引用计数算法实现简单,效率也很高

    缺点:很难解决对象之间相互循环引用时的对象存活判断,例如对象A和B相互引用对方,即使A和B永远都不会再被访问,但是因为AB彼此持有对方的引用导致,AB的计数器永远不会为0,也就不会死亡,引用计数器无法通知GC收集器回收它们,正是因为这一点,主流的JVM都没有选用引用计数法来管理内存。

  • 可达性分析算法:通过一系列的GC Root对象作为起点,从这些起点出发向下搜索,搜索所走过的痕迹称为引用链,当一个对象到起点GC Root没有任何引用链相连接时,就说明该对象是不可用的

    如图1234到GC Root都是可达的因此都是可用的,567都是不可用的。

  • 扩展什么是引用:如果引用类型的数据中存储的数值代表的是另一块内存的起始地址,就称这块内存为一个引用,在这种定义下,一个对象只有被引用和未被引用两种状态,当我们遇到下面这种对象就显得有心无力了:当内存空间足够时,对象保留,内存紧张时,则被抛弃;

    对于这种对象,Java在1.2版本之后对引用进行了加强,提出了强引用、软引用、弱引用和虚引用4种引用类型,引用强度依次递减,下面我们将依次介绍:

    强引用:在代码中普通存在的对象,例如直接new出来的对象,这类对象只要强引用还存在,垃圾收集器永远不会回收被引用的对象;

    软引用:描述一些还有用但是并非必需的对象,这类对象在将要发生内存溢出之前,会被列进回收范围之中进行第二次回收,如果在此次回收中还是没有足够的内存,就会抛出内存溢出异常(SoftReference);

    弱引用:描述一些非必需的对象,这类对象只能存活到下一次垃圾回收之前,当垃圾收集器回收时,无论当前内存是否足够,被弱引用关联的对象都会被回收掉(WeakReference);

    虚引用:最弱的一个引用类型,被虚引用关联的对象完全不会影响其生存时间,可以理解为没有引用一样,但是又有点区别,区别在于,弱引用关联的对象在被收集器回收的时候能收到一个系统回收通知(PhantomReference);

 

对象死亡的过程?

注释:finalize()方法可以使用try-finally替换

 

方法区如何回收?

方法区(HotSpot永久代)回收其实是一个不常被关注的地方,主要原因在于两点,第一:虚拟机规范中不要求对方法区进行回收;第二点:方法区回收的性价比比较低,回收效率比较低。但是我们还是做个了解比较好,接下来我们就讲下方法区的回收。

主要分为两个方面:废弃常量和无用的类

废弃常量:如果常量池中的某个常量不被任何对象引用,也没有任何地方引用这个字面量,则会在垃圾回收的时候,被清理出常量池(常量池中其他类、方法、字段也类似);

无用的类:无用的类需要满足下面3点才会被回收

  • 该类所有的实例都已经被回收,即堆中不存在该类的任何实例

  • 加载该类的ClassLoader已经被回收

  • 该类对应的class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法

当无用的类满足上述3点即满足回收条件,但是具体是否被回收还可以由-Xnoclassgc参数来控制

 

以上就是今天的所有内容,下节我们将隆重介绍几大垃圾收集算法。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM系列之对象是否存活 的相关文章

  • Oracle 的商业 Hotspot JVM 相对于 OpenJDK 有哪些性能优势?

    正如这个问题中所描述的 OpenJDK 与 Java HotspotVM https stackoverflow com q 44335605 1593077 Oracle 的商业 Hotspot JVM 本质上是 OpenJDK 加上一些
  • java.library.path 中没有字体管理器

    以下代码在我的桌面上运行得很好 BufferedImage image new BufferedImage width height BufferedImage TYPE INT RGB Graphics g image getGraphi
  • 在 HP Load Runner 的 VuGen 中加载 javai.dll 时出现错误

    当我尝试在 HP load runner 的 VuGen 中编译一个简单的脚本时 无法启动 JVM 并出现以下错误 Java VM Internal Error Getting Error Loading javai dll 我在用着 HP
  • Java GuardedString - 用于加密的随机密钥是否存储在 Java 堆内存中?如果不是,那么密钥保存在哪里?

    Oracle 的 org identityconnectors common security GuardedString 要转换为 GuardedString 的原始数据需要由 EncryptorImpl class 随机生成的加密密钥
  • 强制jvm返回本机内存[重复]

    这个问题在这里已经有答案了 我时不时地运行需要大量内存的 eclipse 任务 因此 当任务运行时 jvm 会消耗大约 2 3GB 的 RAM 这是可以的 但是一旦 jvm 占用了该内存 它就不会释放它 并且我遇到了一种情况 堆中已用内存约
  • 当目标是属性时,@Throws 不起作用

    在看的同时这个问题 https stackoverflow com q 47737288 7366707 我注意到申请 Throws to a get or setuse site 没有影响 此外 唯一有效的目标 for Throws ar
  • Java 类:匿名类、嵌套类、私有类

    有人能解释一下Java中匿名类 嵌套类和私有类之间的区别吗 我想知道与每个相关的运行时成本以及每个编译器的方法 这样我就可以掌握哪个最适合用于例如性能 编译器优化的潜力 内存使用以及其他 Java 编码人员的普遍可接受性 我所说的匿名类是指
  • Java:为什么它使用固定数量的内存?或者它如何管理内存?

    JVM 似乎使用了一些固定数量的内存 至少我经常看到参数 Xmx 对于最大尺寸 和 Xms 对于初始大小 这表明 我感觉 Java 应用程序不能很好地处理内存 我注意到一些事情 即使一些非常小的示例演示应用程序也会加载大量内存 也许这是因为
  • 抛出 Java 异常时是否会生成堆栈跟踪?

    这是假设我们不调用 printstacktrace 方法 只是抛出和捕获 我们正在考虑这样做是为了解决一些性能瓶颈 不 堆栈跟踪是在构造异常对象时生成的 而不是在抛出异常对象时生成的 Throwable 构造函数调用 fillInStack
  • 通过SOCKS代理连接Kafka

    我有一个在 AWS 上运行的 Kafka 集群 我想用标准连接到集群卡夫卡控制台消费者从我的应用程序服务器 应用程序服务器可以通过 SOCKS 代理访问互联网 无需身份验证 如何告诉 Kafka 客户端通过代理进行连接 我尝试了很多事情 包
  • 无法为对象堆保留足够的空间

    每次尝试运行该程序时 我都会重复出现以下异常 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机 我尝试增加虚拟内存 页面大小 和 RAM 大小 但无济于事 我怎样才能消除这个错误 运行 JVM XX MaxHeap
  • 是什么让热部署成为“难题”?

    在工作中 我们经常遇到这样的问题 永久代内存不足 http www jroller com agileanswers entry preventing java s java lang例外 团队负责人认为这是 JVM 中的一个错误 与代码的
  • Dart/Flutter 如何编译到 Android?

    我找不到任何具体的资源 Dart 是否被编译到 JVM 或者 Google 的团队是否编译了 Dart VM 以在 JVM 上运行 然后在 JVM 内的 Dart VM 中运行 Dart 前者更有意义 并且符合 无桥 的口号 但后者似乎更符
  • Java 比 Xmx 参数消耗更多内存

    我有一个非常简单的 Web 服务器类 基于 Java SEHttpServer class 当我使用此命令启动编译的类来限制内存使用时 java Xmx5m Xss5m Xrs Xint Xbatch Test 现在如果我使用检查内存top
  • 了解 Sun JVM [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Eclipse 找不到 javaw.exe

    当我启动 eclipse 时 我遇到这个问题 javaw exe在我的电脑中的位置是C Program Files Java jre7 bin 我尝试更改路径环境变量 然后出现不同的错误 例如 JRE 更新到 jre1 8 0 111 后
  • 使用 jni 从 C 调用 java 函数

    我正在编写一个简单的程序来从我的 C 程序调用 Java 函数 以下是我的代码 include
  • 从 Java 内部限制 CPU

    我在这个 和其他 论坛中看到了许多具有相同标题的问题 但似乎没有一个问题能完全解决我的问题 就是这个 我有一个 JVM 它占用了托管它的机器上的所有 CPU 我想限制它 但是我不能依赖任何限制工具 技术external到 Java 因为我无
  • JVM 最大堆大小可以是动态的吗?

    JVM Xmx 参数允许将 JVM 的最大堆大小设置为某个值 但是 有没有办法让这个价值动态化呢 换句话说 我想告诉 JVM 看 如果你需要它 就继续从系统中获取 RAM 直到系统退出 提问原因分为两部分 首先 所讨论的应用程序可以根据用户
  • 运行具有外部依赖项的 Scala 脚本

    我在 Users joe scala lib 下有以下 jar commons codec 1 4 jar httpclient 4 1 1 jar httpcore 4 1 jar commons logging 1 1 1 jar ht

随机推荐