网站正在建设中提示页,商城建设公司,横沥建设网站,天津设计公司有哪些视频讲解地址
学习文档 一、内存区域 区域描述线程私有如何溢出程序计数器为了线程切换后能恢复到正确的执行位置#xff0c;每个线程都要有一个独立的程序计数器。✅唯一一个不会内存溢出的地方虚拟机栈1. 每个方法执行的时候#xff0c;Java虚拟机都会同步创建一个栈帧用于…视频讲解地址
学习文档 一、内存区域 区域描述线程私有如何溢出程序计数器为了线程切换后能恢复到正确的执行位置每个线程都要有一个独立的程序计数器。✅唯一一个不会内存溢出的地方虚拟机栈1. 每个方法执行的时候Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、方法出口等信息。 2. 每一个方法从调用到执行完毕都对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 3. 局部变量表存储了编译期可知的各种Java基本数据类型和对象引用。✅1. 线程请求的栈深度大于虚拟机所允许的深度时抛出 StackOverFlowError异常。 2. 栈扩容时无法申请到足够内存的时候抛出 OutOfMemoryError。本地方法栈和虚拟机栈类似本地方法栈是为本地Native方法服务的✅同【虚拟机栈】方法区线程共享用于存放被虚拟机加载后的类型信息、常量、静态变量、即时编译器编译后的代码缓存数据。 注运行时常量池、元空间都属于方法区的一部分。❌无法满足新的内存分配会抛出 OutOfMemoryError堆垃圾收集的主要区域1. 基本上所有的对象都是在堆上分配的。 2. Java堆可以处于物理上不连续的内存空间中但在逻辑上它应该被视为连续的。❌无法满足新的内存分配会抛出 OutOfMemoryError直接内存NIO通过使用Native函数库直接分配对外内存。不受Java堆大小限制但是受机器的物理内存限制。❌无法满足新的内存分配会抛出 OutOfMemoryError 堆其实就是一大块内存区域是用来存放对象的对于一个应用来说最耗费内存的就是“对象”。因为在运行的过程中会创建无数个对象所以内存回收垃圾回收的时候主要就是针对堆的垃圾进行回收。 常见的堆划分是
把堆分为新生代和老年代新生代分为一个Eden区和两个Survivor区它们的内存占比是 8:1:1注但G1却不是这样的它把堆分成数个大小相同的Regin块 二、回收时机 上面我们谈到内存空间内存是有限的想要健康持续的运行下去就一定要回收“垃圾”。
那怎么判定一个对象是不是垃圾呢就成了新的问题。
算法描述备注引用计数算法当某个对象被引用的时候引用计数器就加一引用失效时就减一当没有引用的时候就说明可以被回收了。几乎没有使用它的因为它无法解决循环依赖的问题。可达性分析某些对象被定义为根GC Roots从GC Roots向下搜索的路径成为“引用链”如果某个对象到GC Roots间没有任何引用那说明它不可达它就可以被回收了。目前都是用这种算法。 GC Roots并不是一个固定的对象它是一组对象
在虚拟机栈引用的对象譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。在方法区中类静态属性引用的对象譬如Java类的引用类型静态变量。在方法区中常量引用的对象譬如字符串常量池里的引用。在本地方法栈中JNI即 Native方法引用的对象。Java虚拟机内部的引用如基本数据类型对应的Class对象。所有被同步锁Sync持有的对象。除了这些固定的GC Roots根据不同的垃圾回收器还可以有其他“临时性”地加入。 一个对象是否可以被回收是要看有没有被GC Roots触达而不是仅仅是 触达 不管是引用计数算法还是可达性分析都提到了引用。Java中的引用并不是简单的引用它有四种不同的引用
引用类型描述强引用被强引用的对象不会被回收。 new 的方式创建就是产生强引用。软引用被软应用的对象只有在内存不足的时候才会被回收。弱引用被弱引用的对象在下一次垃圾回收的时候就会被回收。虚引用虚引用又被称为幽灵引用它和回收没太大关系只是在回收的时候会收到一个系统的通知。 三、回收算法 已经知道了哪些对象是可以回收的那就需要按照某种回收算法去回收它们。 名称描述优缺点标记-清除标记所有未被引用的对象在GC的时候清空它们。优点简单直观 缺点会产生大量的内存碎片。如果下次需要分配一个大对象没有连续空间的时候会提前触发GC。标记-整理标记所有被引用的对象将还存活的对象移动到一端然后清除边界外的内存。优点减少了内存碎片相对于标记-清除减少了碎片化问题。 缺点移动对象需要成本。标记-复制将内存划分成两个相同大小的块每次只使用其中一块。当一块的内存用完了就将还存活的对象复制到另外一块然后再把之前那块空间清空。 IBM公司有一项研究的结论是新生代中98%的对象熬不过第一轮回收所以不必按照 1:1 的比例来划分。 新生代分为三个区一个Eden、两个Survivor对象优先分配在Eden区每次只使用Eden和一个Survivor在垃圾回收的时候把还存活的对象移动到另外一个没有被使用的Survivor中。如果Survivor区空间不够会把对象移动到老年代。 注 1. 两个Survivor在有的地方被称为From和 To或 S0、S1 2. 默认情况下Eden和两个Survivor的比例是 8:1:1优点减少了内存碎片适用于对象生命周期短的场景。 缺点空间浪费和复制成本。 四、回收器 回收算法是理论回收器是实践不同回收器都是基于理论进行真正的实践在讨论回收器之前需要先了解下面几个点
STWStop The World 的缩写意味着在GC的时候其它线程无法工作。并行、并发多个GC线程一起工作就是并行GC线程和用户线程一起工作就是并发。吞吐量运行用户代码时间 / 运行用户代码时间垃圾回收时间通过算法可以得出想要提高吞吐量就必须减少垃圾回收耗时。 下面是各个回收器的作用域连线表示它们可以组合使用红色线表示JDK9已经不推荐了。 名称描述效率STW回收算法作用域目标使用场景回收步骤Serial它是单线程工作的且在进行垃圾回收的时候必须暂停所有的工作线程。串行是标记-复制新生代快速的回收1. 在客户端模式下的默认新生代收集器。 2. 对于内存资源不多的情况下它是所有收集器里额外内存消耗最小的。Serial Old同上串行是标记-整理老年代快速的回收同上同上ParNew它支持多线程并行回收垃圾其它与Serial收集器没什么大的差别。并行是标记-复制新生代快速的回收是除了Serial之外唯一可以和CMS收集器配合工作的。Parallel Scavenge它和ParNew有很多相似的地方不同的是它关注的是 达到一个可控制的吞吐量。并行是标记-复制新生代提高吞吐量大规模的后台服务、批处理任务等对吞吐量要求高的场景。同上Parallel Old同上并行是标记-整理老年代提高吞吐量同上同上CMSCMS可以并发的去执行并且可以部分STW的回收器。并发部分STW标记-清除老年代快速的回收对延迟敏感的应用需要较短垃圾回收停顿时间。G11. G1将堆分成多个大小相同的Regin大小在 1-32MB默认是 2048个每一个Regin都可以充当新生代或老年代中的某个区。 2. Regin中还有一个特殊的区域 Humongous Regin大对象直接分在老年代防止了反复拷贝移动 G1规定大小超过普通Regin一半的对象是大对象大对象就存在Humongous Regin它会独占一个、或多个连续Region。 3. 使用 Mixed GC 回收下面讲并发部分STW标记-整理通吃满足高吞吐量的同时尽可能地减少垃圾回收耗时大内存应用、需要可预测停顿时间的应用JDK9开始成为默认的垃圾回收器。G1对于CMS并不是完全的碾压G1的实现更加复杂所以它所额外使用的内存和程序运行时的负载都比CMS高。 CMS和G1的对比
CMS会产生内存碎片且无法回收浮动垃圾因为清理的时候是并发的这时候工作线程可能产生新的垃圾关注点CMS是快速的回收G1是在限定的时间内这个时间可以自定义最大限度的回收会把垃圾排序然后回收收益最大的部分作用范围CMS是作用于老年代G1是都可以内存分布G1对堆内存进行了大小相同的Regin划分在Regin的基础上再进行新生代和老年代划分CMS是传统的新生代、老年代分布性能CMS对CPU资源非常敏感可能会影响正常请求因为回收的时候很多阶段是并发的G1对内存要求较高想想它对堆做了那么复杂的划分和逻辑这些都是需要额外内存和cup支持的所以更适合大堆G1的目的是代替CMSJDK9之后默认的垃圾收集器就是G1但CMS并不是一无是处在内存小的时候还是更合适的 MinorGC、MajorGC、Full GC、Mixed GC
MinorGC是对新生代回收时候的GC有时候也叫 youngGCMajorGC是针对老年代的垃圾回收操作。出现 Major GC 通常会出现至少一次 Minor GC。有时候也叫 OldGCFull GCFull GC 会清理整个堆和方法区包括年轻代、老年代和方法区。FullGC对于方法区的回收主要是满足下面三个条件 Java堆中不存在该类的任何实例对象 加载该类的类加载器已经被回收 该类对应的java.lang.Class对象不在任何地方被引用且无法在任何地方通过反射访问该类的方法。
Mixed GC它是G1才有的。不再是每次回收新生代、老年代了而是把内存排序后回收利益最大的这也是G1这个名字的由来。 五、其它 注G1并不是终点后面还有ZGC它关注更低的延迟但现在大家都还没用到暂时先不去学习了 参考
本文严重参考了《深入理解Java虚拟机》这本书https://tech.meituan.com/2016/09/23/g1.html