美文网首页
JVM-线程,内存 ,finalize

JVM-线程,内存 ,finalize

作者: 简书徐小耳 | 来源:发表于2019-03-01 00:26 被阅读0次

目前jvm的后台线程有如下:

image.png

JVM内存区域

image.png

永久代/方法区

  • 被 JVM 加载的类信息、 常量、 静态变量、 即时编译器编译后的代码等数据. HotSpot VM把GC分代收集扩展至方法区, 即使用Java堆的永久代来实现方法区, 这样 HotSpot 的垃圾收集器就可以像管理 Java 堆一样管理这部分内存,而不必为方法区开发专门的内存管理器(永久带的内存回收的主要目标是针对常量池的回收和类型的卸载, 因此收益一般很小)

永久代和元数据区

  • 在 Java8 中, 永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,元空间与永久代之间最大的区别在于: 元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。 类的元数据放入 nativememory, 字符串池和类的静态变量放入 java 堆中, 这样可以加载多少类的元数据就不再由MaxPermSize 控制, 而由系统的实际可用空间来控制。

finalize方法的机制

  • 一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存.所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作.
  • finalize只会调用一次 如果我们在finalize方法内部救活了这个对象 然后再下次回收会直接执行。
  • 如果这个对象被判定为有必要执行 finalize 方法,那么这个对象将会放置在一个叫做 F-Queue 的队列之中,并在稍后由一个虚拟机自动建立的,优先级为 8 的 Finalizer 线程去执行它。(JVM 不保证这些对象的方法都被执行)

真实的逻辑

  • 只要实现finalize方法的类都会被JVM调用了Finalizer类的register方法把我们的类包装成Finalizer。并把这个Finalizer加入到 unfinalized 的链表中。
  • 而Finalizer是FinalReference类型的,当我们的自己的类快被回收则Finalizer会被加入到ReferenceQueue里面(通过Reference的线程进行回收到队列)
  • 然后我们finalizer线程去队列里面取出Finalizer然后执行finalize方法。
  • 通过这个我们知道当我们的Reference放入队列的时候,持有的对象还没有被回收只是被标记要回收了。(对于其他引用可能已经回收了 我们这边没有回收是因为finalize链表的存在)
  • 当我们在finalize方法救活这个对象则下次再被释放的时候虽然还会放入队列 但是不会再执行finalize方法。这是因为我们执行完了finalize方法之后会clear referent。这样下次再执行finalize发现referent不存在 则不会执行finalize方法。

总结

  • finalizer对象因为Finalizer的引用而变成了一个临时的强引用(链表类似Cleaner),即使没有其他的强引用了,还是无法立即被回收;
  • finalizer对象至少经历两次GC才能被回收,因为只有在FinalizerThread执行完了finalizer对象的finalize方法的情况下才有可能被下次gc回收,而有可能期间已经经历过多次gc了,但是一直还没执行finalizer对象的finalize方法;
  • cpu资源比较稀缺的情况下FinalizerThread线程有可能因为优先级比较低而延迟执行finalizer对象的finalize方法;
  • 因为finalizer对象的finalize方法迟迟没有执行,有可能会导致大部分finalizer对象进入到old分代,此时容易引发old分代的gc,甚至fullgc,gc暂停时间明显变长;
  • finalizer对象的finalize方法被调用了,但是这个对象其实还并没有被回收,虽然可能在不久的将来会被回收。
  • 一般情况下弱引用进入队列时候referent已经被回收,虚引用则对象还没被回收(即将被回收)

相关文章

  • JVM-线程,内存 ,finalize

    目前jvm的后台线程有如下: JVM内存区域 永久代/方法区 被 JVM 加载的类信息、 常量、 静态变量、 即时...

  • JVM-常见参数

    [TOC] JVM-常见参数 实验平台MacOSmacOS Catalina 10.15内存 8 GB 2133 ...

  • should

    1finalize方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前...

  • JVM-对象内存布局

    jvm-对象内存布局 对象内存结构概述 对象的创建过程: jvm将对象所在的class文件加载到方法区中 jvm读...

  • JVM-内存-内存溢出

    jvm内存结构 堆区jvm内存区域young区s0+s1s0和s1在同一时间点,只有一个在使用s0和s1是相等的e...

  • JVM-内存结构

    1.Java内存结构结构图如下: 1>方法区:用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代...

  • JVM-内存模型

    Java并发是基于共享内存模型实现的。学习并深入地理解__Java内存模型__,有助于开发人员了解Java的线程间...

  • jvm-内存模型

    一、学习jvm的目的 jmm规范(java memory model),定义了多线程环境下,线程间的交互行为,保证...

  • JVM-内存模型

    前言 近几个月学习了儒猿技术窝的专栏《从 0 开始带你成为JVM实战高手[https://apppukyptrl1...

  • finalize,内存回收函数

网友评论

      本文标题:JVM-线程,内存 ,finalize

      本文链接:https://www.haomeiwen.com/subject/uokcuqtx.html