JVM
inet_ygssoftware
西南大学毕业 在各种大厂游荡 也是大厂中的工具人 各种架构设计 工具类封装 开源组件分享 职业生涯中都接触和参与其中
展开
-
G1垃圾收集器深度剖析
G1垃圾收集器深度剖析一、G1垃圾收集器概述1.1 思考开始学习前,抛出两个常见面试问题:1.G1的回收原理是什么?为什么G1比传统的GC回收性能好?2.为什么G1如此完美仍然会有ZGC?简单的回顾下CMS垃圾回收机制,下面介绍了一个极端的场景(而且是经常发生的) 在发生Minor GC时,由于Survivor区已经放不下了,多出的对象只能提升(Promotion)到老年代。但是此时老年代因为空间碎片的缘故,会发生Concurrent mode failure的错误。这个时候,就需要降级为Serial原创 2021-05-27 00:14:51 · 133206 阅读 · 4 评论 -
造成OOM的原因有哪几种?
堆内存不足是最常见的 OOM 原因之一,抛出的错误信息是“java.lang.OutOfMemoryError:Java heap space”,原因可能千奇百怪,例如,可能存在内存泄漏问题;也很有可能就是堆的大小不合理,比如我们要处理比较可观的数据量,但是没有显式指定 JVM 堆大小或者指定数值偏小;或者出现 JVM 处理引用不及时,导致堆积起来,内存无法释放等。虚拟机栈和本地方法栈,这里要稍微复杂一点。如果我们写一段程序不断的进行递归调用,而且没有退出条件,就会导致不断地进行压栈。类似这种情况,JV.原创 2021-05-26 00:35:14 · 143027 阅读 · 1 评论 -
如何提高JVM的性能?
新对象预留在年轻代 通过设置一个较大的年轻代预留新对象,设置合理的 Survivor 区并且提供 Survivor 区的使用率,可以将年轻对象保存在年轻代。大对象进入年老代 使用参数-XX:PetenureSizeThreshold 设置大对象直接进入年老代的阈值设置对象进入年老代的年龄 这个阈值的最大值可以通过参数-XX:MaxTenuringThreshold 来设置,默认值是 15稳定的 Java 堆 获得一个稳定的堆大小的方法是使-Xms 和-Xmx 的大小一致,即最大堆和最小..原创 2021-05-26 00:33:45 · 142595 阅读 · 1 评论 -
如何自定义类加载器?
自定义类加载器,常见的场景有:实现类似进程内隔离,类加载器实际上用作不同的命名空间,以提供类似容器、模块化的效果。例如,两个模块依赖于某个类库的不同版本,如果分别被不同的容器加载,就可以互不干扰。这个方面的集大成者是Java EE和OSGI、JPMS等框架。应用需要从不同的数据源获取类定义信息,例如网络数据源,而不是本地文件系统。需要自己操纵字节码,动态修改或者生成类型从本地路径 load class 的例子:public class CustomClassLoader extends Cla原创 2021-05-26 00:31:17 · 143026 阅读 · 1 评论 -
JVM类加载过程
一般来说,我们把 Java 的类加载过程分为三个主要步骤:加载、链接、初始化。 首先是加载阶段(Loading),它是 Java 将字节码数据从不同的数据源读取到 JVM 中,并映射为 JVM 认可的数据结构(Class 对象),这里的数据源可能是各种各样的形态,如 jar 文件、class 文件,甚至是网络数据源等;如果输入数据不是 ClassFile 的结构,则会抛出 ClassFormatError。加载阶段是用户参与的阶段,我们可以自定义类加载器,去实现自己的类加载过程。第二阶段是链接(Linki原创 2021-05-26 00:28:49 · 142972 阅读 · 0 评论 -
什么是空间分配担保策略?
VM在发生Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间,如果大于,则此次Minor GC是安全的如果小于,则虚拟机会查看HandlePromotionFailure设置项的值是否允许担保失败。 如果HandlePromotionFailure=true,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的对象的平均大小,如果大于则尝试进行一次Minor GC,但这次Minor GC依然是有风险的; 如果小于或者HandlePromotionF原创 2021-05-26 00:27:03 · 143225 阅读 · 1 评论 -
什么时候对象会进入老年代?
新创建出来的对象一开始都会停留在新生代中,但随着JVM的运行,有些存活的长的对象会慢慢的移动到老年代中。1. 根据对象年龄JVM会给对象增加一个年龄(age)的计数器,对象每“熬过”一次GC,年龄就要+1,待对象到达设置的阈值(默认为15岁)就会被移移动到老年代,可通过-XX:MaxTenuringThreshold调整这个阈值。一次Minor GC后,对象年龄就会+1,达到阈值的对象就移动到老年代,其他存活下来的对象会继续保留在新生代中。2. 动态年龄判断根据对象年龄有另外一个策略也会让对象原创 2021-05-26 00:25:22 · 144474 阅读 · 2 评论 -
常见的垃圾回收器算法有哪些,各有什么优劣?
标记清除这种算法分两分: 标记、清除两个阶段,标记阶段是从根集合(GC Root)开始扫描,每到达一个对象就会标记该对象为存活状态,清除阶段在扫描完成之后将没有标记的对象给清除掉。这个算法有个缺陷就是会产生内存碎片,如上图B被清除掉后会留下一块内存区域,如果后面需要分配大的对象就会导致没有连续的内存可供使用。标记整理标记整理就没有 内存碎片的问题了,也是从根集合(GC Root)开始扫描进行标记然后清除无用的对象,清除完成后它会整理内存。这样内存就是连续的了,但是产生的另外一个问题是原创 2021-05-26 00:20:34 · 142971 阅读 · 0 评论 -
什么时候对象可以被收回?
JVM判断对象回收有两种方式: 引用记数、GC Roots,引用记数比较简单,JVM为每个对象维护一个引用计数,假设A对象引用计数为零说明没有任务对象引用A对象,那A对象就可以被回收了,但是引用计数有个缺点就是无法解决循环引用的问题。GC Roots通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明对象是不可用的。在Java中,可以作为GC Roots的对象包括下面几种:虚拟机栈中引用的对象原创 2021-05-26 00:16:45 · 142969 阅读 · 0 评论 -
死锁与活锁的区别,死锁与饥饿的区别?
**死锁:**是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。产生死锁的必要条件:1、互斥条件:所谓互斥就是进程在某一时间内独占资源。2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。3、不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。**活锁:**任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,原创 2021-05-26 00:12:02 · 143416 阅读 · 1 评论 -
JVM内存模型
方法区方法区与Java堆一样,是各个线程共享的区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译(JIT)后的代码等数据。对于JDK1.8之前的HotSpot虚拟机而言,很多人经常将方法区称为我们上图中所描述的永久代,实际上两者并不等价,因为这仅仅是HotSpot的设计团队选择利用永久代来实现方法区而言。同时对于其他虚拟机比如IBM J9中是不存在永久代的概念的。其实,移除永久代的工作从JDK1.7就开始了。JDK1.7中,存储在永久代的部分数据就已经转移到了Java Heap或者是 N.原创 2021-05-26 00:08:29 · 142836 阅读 · 0 评论 -
JVM内存模型和类加载运行机制
JVM内存模型和类加载运行机制JVM内存模型运行一个 Java 应用程序,必须要先安装 JDK 或者 JRE 包。因为 Java 应用在编译后会变成字节码,通过字节码运行在 JVM 中,而 JVM 是 JRE 的核心组成部分。JVM 不仅承担了 Java 字节码的分析和执行,同时也内置了自动内存分配管理机制。这个机制可以大大降低手动分配回收机制可能带来的内存泄露和内存溢出风险,使 Java 开发人员不需要关注每个对象的内存分配以及回收,从而更专注于业务本身。在 Java 中,JVM 内存模型主要分为堆原创 2021-05-19 22:26:11 · 164246 阅读 · 0 评论