深圳建设银行宝安支行网站市场营销在线课程

news/2025/10/4 20:11:38/文章来源:
深圳建设银行宝安支行网站,市场营销在线课程,广州有什么好玩的游乐场,网络推广方式主要有1. JVM快速入门 从面试开始#xff1a; 请谈谈你对JVM 的理解#xff1f;java8 的虚拟机有什么更新#xff1f; 什么是OOM #xff1f;什么是StackOverflowError#xff1f;有哪些方法分析#xff1f; JVM 的常用参数调优你知道哪些#xff1f; 内存快照抓取和MAT分…1. JVM快速入门 从面试开始 请谈谈你对JVM 的理解java8 的虚拟机有什么更新 什么是OOM 什么是StackOverflowError有哪些方法分析 JVM 的常用参数调优你知道哪些 内存快照抓取和MAT分析DUMP文件知道吗 谈谈JVM中对类加载器你的认识 ​ 位置JVM是运行在操作系统之上的它与硬件没有直接的交互 1.1. 结构图 方法区存储已被虚拟机加载的类元数据信息(元空间) 堆存放对象实例几乎所有的对象实例都在这里分配内存 虚拟机栈虚拟机栈描述的是Java方法执行的内存模型每个方法被执行的时候都会同时创建一个栈帧Stack Frame用于存储局部变量表、操作栈、动态链接、方法出口等信息 程序计数器当前线程所执行的字节码的行号指示器 本地方法栈本地方法栈则是为虚拟机使用到的Native方法服务。 1.2. 类加载器ClassLoader 负责加载class文件class文件在文件开头有特定的文件标示并且ClassLoader只负责class文件的加载至于它是否可以运行则由Execution Engine决定。 类加载器分为四种前三种为虚拟机自带的加载器。 启动类加载器BootstrapC 负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class由C实现不是ClassLoader子类 扩展类加载器ExtensionJava 负责加载java平台中扩展功能的一些jar包包括$JAVA_HOME中jre/lib/ext/*.jar或-Djava.ext.dirs指定目录下的jar包 应用程序类加载器AppClassLoaderJava 也叫系统类加载器负责加载classpath中指定的jar包及目录中class 用户自定义加载器 Java.lang.ClassLoader的子类用户可以定制类的加载方式 工作过程 1、当AppClassLoader加载一个class时它首先不会自己去尝试加载这个类而是把类加载请求委派给父类加载器ExtClassLoader去完成。2、当ExtClassLoader加载一个class时它首先也不会自己去尝试加载这个类而是把类加载请求委派给BootStrapClassLoader去完成。3、如果BootStrapClassLoader加载失败例如在$JAVA_HOME/jre/lib里未查找到该class会使用ExtClassLoader来尝试加载4、若ExtClassLoader也加载失败则会使用AppClassLoader来加载5、如果AppClassLoader也加载失败则会报出异常ClassNotFoundException 其实这就是所谓的双亲委派模型。简单来说如果一个类加载器收到了类加载的请求它首先不会自己去尝试加载这个类而是把请求委托给父加载器去完成依次向上。 好处防止内存中出现多份同样的字节码(安全性角度) 比如加载位于 rt.jar 包中的类 java.lang.Object不管是哪个加载器加载这个类最终都是委托给顶层的启动类加载器进行加载这样就保证了使用不同的类加载器最终得到的都是同样一个 Object对象。 写段儿代码演示类加载器 public class Demo {public Demo() {super();}public static void main(String[] args) {Object obj new Object();String s new String();Demo demo new Demo();System.out.println(obj.getClass().getClassLoader());System.out.println(s.getClass().getClassLoader());System.out.println(demo.getClass().getClassLoader().getParent().getParent());System.out.println(demo.getClass().getClassLoader().getParent());System.out.println(demo.getClass().getClassLoader());} }打印控制台中的sun.misc.Launcher是一个java虚拟机的入口应用 由于BootStrap ClassLoader是用c写的所以在返回该ClassLoader时会返回null 1.3. 执行引擎Execution Engine Execution Engine执行引擎负责解释命令提交操作系统执行。 1.4. 本地接口Native Interface ​ 本地接口的作用是融合不同的编程语言为 Java 所用它的初衷是融合 C/C程序Java 诞生的时候是 C/C横行的时候要想立足必须有调用 C/C程序于是就在内存中专门开辟了一块区域处理标记为native的代码它的具体做法是 Native Method Stack中登记 native方法在Execution Engine 执行时加载native libraies。 ​ 目前该方法使用的越来越少了除非是与硬件有关的应用比如通过Java程序驱动打印机或者Java系统管理生产设备在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达比如可以使用 Socket通信也可以使用Web Service等等不多做介绍。 1.5. Native Method Stack 它的具体做法是Native Method Stack中登记native方法在Execution Engine 执行时加载本地方法库。 1.6. PC寄存器 每个线程都有一个程序计数器是线程私有的就是一个指针指向方法区中的方法字节码用来存储指向下一条指令的地址即 将要执行的指令代码由执行引擎读取下一条指令是一个非常小的内存空间几乎可以忽略不记。 1.7. Method Area方法区 方法区是被所有线程共享所有字段和方法字节码以及一些特殊方法如构造函数接口代码也在此定义。简单说所有定义的方法的信息都保存在该区域此区属于共享区间。 静态变量常量类信息(构造方法/接口定义)运行时常量池存在方法区中但是对象实例存在堆内存中和方法区无关。 2. stack栈 Stack 栈是什么 ​ 栈也叫栈内存主管Java程序的运行是在线程创建时创建它的生命期是跟随线程的生命期线程结束栈内存也就释放对于栈来说不存在垃圾回收问题只要线程一结束该栈就Over生命周期和线程一致是线程私有的。8种基本类型的变量对象的引用变量实例方法都是在函数的栈内存中分配。 栈存储什么? 栈中的数据都是以栈帧Stack Frame的格式存在栈帧是一个内存区块是一个数据集是一个有关方法(Method)和运行期数据的数据集。 栈帧中主要保存3 类数据 本地变量Local Variables输入参数和输出参数以及方法内的变量。 栈操作Operand Stack记录出栈、入栈的操作。 栈帧数据Frame Data包括类文件、方法等等。 栈运行原理 当一个方法A被调用时就产生了一个栈帧 F1并被压入到栈中 A方法又调用了 B方法于是产生栈帧 F2 也被压入栈 B方法又调用了 C方法于是产生栈帧 F3 也被压入栈 …… 执行完毕后先弹出F3栈帧再弹出F2栈帧再弹出F1栈帧…… 遵循“先进后出”或者“后进先出”原则。 图示在一个栈中有两个栈帧 栈帧 2是最先被调用的方法先入栈 然后方法 2 又调用了方法1栈帧 1处于栈顶的位置 栈帧 2 处于栈底执行完毕后依次弹出栈帧 1和栈帧 2 线程结束栈释放。 每执行一个方法都会产生一个栈帧保存到栈(后进先出)的顶部顶部栈就是当前的方法该方法执行完毕 后会自动将此栈帧出栈。 常见问题栈溢出Exception in thread “main” java.lang.StackOverflowError 通常出现在递归调用时。 3. 堆 堆栈方法区的关系 HotSpot是使用指针的方式来访问对象 Java堆中会存放访问类元数据的地址 reference存储的就是对象的地址 三种JVM •Sun公司的HotSpot •BEA公司的JRockit •IBM公司的J9 VM 3.1. 堆体系概述 Java7之前 Heap 堆一个JVM实例只存在一个堆内存堆内存的大小是可以调节的。类加载器读取了类文件后需要把类、方法、常变量放到堆内存中保存所有引用类型的真实信息以方便执行器执行堆内存逻辑上分为三部分 Young Generation Space 新生区 Young/New Tenure generation space 养老区 Old/Tenure Permanent Space 永久区 Perm 也称为新生代年轻代、老年代、永久代持久代。 3.1.1. 新生区 ​ 新生区是对象的诞生、成长、消亡的区域一个对象在这里产生应用最后被垃圾回收器收集结束生命。新生区又分为两部分 伊甸区Eden space和幸存者区Survivor pace 所有的对象都是在伊甸区被new出来的。幸存区有两个 From区Survivor From space和To区Survivor To space。当伊甸园的空间用完时程序又需要创建对象JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC)将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 From区。 MinorGC垃圾回收的过程如下 eden、From 复制到 To年龄1 首先当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到Survivor From区当Eden区再次触发GC的时候会扫描Eden区和From区域对这两个区域进行垃圾回收经过这次回收后还存活的对象则直接复制到To区域如果有对象的年龄已经达到了老年的标准则赋值到老年代区同时把这些对象的年龄1 清空 eden、Survivor From 然后清空Eden和From中的对象 To和 From 互换 最后To和From互换原To成为下一次GC时的From区。部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15)最终如果还是存活,就存入到老年代 大对象特殊情况 如果分配的新对象比较大Eden区放不下但Old区可以放下时对象会被直接分配到Old区即没有晋升这一过程直接到老年代了 MinorGC的过程复制 - 清空 - 互换 3.1.2. 老年代 经历多次GC仍然存在的对象默认是15次老年代的对象比较稳定不会频繁的GC 若养老区也满了那么这个时候将产生MajorGCFullGC进行养老区的内存清理。若养老区执行了Full GC之后发现依然无法进行对象的保存就会产生OOM异常“OutOfMemoryError”。 如果出现java.lang.OutOfMemoryError: Java heap space异常说明Java虚拟机的堆内存不够。原因有二 1Java虚拟机的堆内存设置不够可以通过参数-Xms、-Xmx来调整。 2代码中创建了大量大对象并且长时间不能被垃圾收集器收集存在被引用。 3.1.3. 永久代 ​ 永久存储区是一个常驻内存区域用于存放JDK自身所携带的 Class、Interface 的元数据也就是说它存储的是运行环境必须的类信息被装载进此区域的数据是不会被垃圾回收器回收掉的关闭 JVM 才会释放此区域所占用的内存。 ​ 对于HotSpot虚拟机很多开发者习惯将方法区称之为“永久代(Parmanent Gen)” 但严格本质上说两者不同或者说使用永久代来实现方法区而已永久代是方法区(相当于是一个接口interface)的一个实现。 ​ 实际而言方法区Method Area和堆一样是各个线程共享的内存区域它用于存储虚拟机加载的类信息普通常量静态常量编译器编译后的代码等等虽然JVM规范将方法区描述为堆的一个逻辑部分但它却还有一个别名叫做Non-Heap(非堆)目的就是要和堆分开。 ​ 如果出现java.lang.OutOfMemoryError: PermGen space说明是Java虚拟机对永久代Perm内存设置不够。一般出现这种情况都是程序启动需要加载大量的第三方jar包。例如在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载最终导致Perm区被占满。 Jdk1.6及之前 有永久代常量池1.6在方法区 Jdk1.7 有永久代但已经逐步“去永久代”常量池1.7在堆 Jdk1.8及之后 无永久代常量池1.8在堆中 永久代与元空间的最大区别之处 永久代使用的是jvm的堆内存但是java8以后的元空间并不在虚拟机中而是使用本机物理内存。因此默认情况下元空间的大小仅受本地内存限制。 3.2. 堆参数调优入门 均以JDK1.8HotSpot为例 jdk1.7 jdk1.8 3.2.1. 常用JVM参数 怎么对jvm进行调优通过参数配置 参数备注-Xms初始堆大小。只要启动就占用的堆大小默认是内存的1/64-Xmx最大堆大小。默认是内存的1/4-Xmn新生区堆大小-XX:PrintGCDetails输出详细的GC处理日志 java代码查看jvm堆的默认值大小 Runtime.getRuntime().maxMemory() // 堆的最大值默认是内存的1/4 Runtime.getRuntime().totalMemory() // 堆的当前总大小默认是内存的1/643.2.2. 怎么设置JVM参数 程序运行时可以给该程序设置jvm参数不同的工具设置方式不同。 如果是命令行运行 java -Xmx50m -Xms10m HeapDemoeclipse运行的设置方式如下 idea运行时设置方式如下 3.2.3. 查看堆内存详情 public class Demo2 {public static void main(String[] args) {System.out.print(最大堆大小);System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 M);System.out.print(当前堆大小);System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 M);System.out.println();byte[] b null;for (int i 0; i 10; i) {b new byte[1 * 1024 * 1024];}} }执行前配置参数-Xmx50m -Xms30m -XX:PrintGCDetails 执行看到如下信息 新生代和老年代的堆大小之和是Runtime.getRuntime().totalMemory() 3.2.4. GC演示 public class HeapDemo {public static void main(String args[]) {System.out.println(Begin);System.out.print(最大堆大小Xmx);System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 M);System.out.print(剩余堆大小free mem);System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 M);System.out.print(当前堆大小total mem);System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 M);System.out.println(First Allocated);byte[] b1 new byte[5 * 1024 * 1024];System.out.println(5MB array allocated);System.out.print(剩余堆大小free mem);System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 M);System.out.print(当前堆大小total mem);System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 M);System.out.println(Second Allocated);byte[] b2 new byte[10 * 1024 * 1024];System.out.println(10MB array allocated);System.out.print(剩余堆大小free mem);System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 M);System.out.print(当前堆大小total mem);System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 M);System.out.println(OOM);System.out.println(OOM!!!);System.gc();byte[] b3 new byte[40 * 1024 * 1024];} }jvm参数设置成最大堆内存100M当前堆内存10M-Xmx100m -Xms10m -XX:PrintGCDetails 再次运行可以看到minor GC和full GC日志 3.2.5. OOM演示 把上面案例中的jvm参数改成最大堆内存设置成50M当前堆内存设置成10M执行测试 -Xmx50m -Xms10m Begin剩余堆大小free mem8.186859130859375M 当前堆大小total mem9.5M First Allocated 5MB array allocated 剩余堆大小free mem3.1868438720703125M 当前堆大小total mem9.5M Second Allocated 10MB array allocated 剩余堆大小free mem3.68682861328125M 当前堆大小total mem20.0M OOM OOM!!! Exception in thread main java.lang.OutOfMemoryError: Java heap spaceat com.atguigu.demo.HeapDemo.main(HeapDemo.java:40)实际开发中怎么定位这种错误信息MAT工具 3.3. MAT工具 安装方式eclipse插件市场下载 3.3.1. MAT工具的使用 运行参数-Xmx30m -Xms10m -XX:HeapDumpOnOutOfMemoryError 重新刷新项目看到dump文件 打开 3.3.2. idea分析dump文件 把上例中运行参数改成 -Xmx50m -Xms10m -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPathD:\tmp -XX:HeapDumpPath生成dump文件路径。 再次执行生成C:\tmp\java_pid20328.hprof文件 生成的这个文件怎么打开jdk自带了该类型文件的解读工具jvisualvm.exe 双击打开 文件–装入–选择要打开的文件即可 装入后 3.4. 常用命令行了解 查看java进程jps -l 查看某个java进程所有参数jinfo 进程号 查看某个java进程总结性垃圾回收统计jstat -gc 20292 3.5. jvm结构总结 4. GC垃圾回收 面试题 JVM内存模型以及分区需要详细到每个区放什么堆里面的分区Edensurvival from to老年代各自的特点。GC的三种收集方法标记清除、标记整理、复制算法的原理与特点分别用在什么地方Minor GC与Full GC分别在什么时候发生 JVM垃圾判定算法对象已死 引用计数法(Reference-Counting)可达性分析算法根搜索算法 GC垃圾回收主要有四大算法怎么找到已死对象并清除 复制算法(Copying)标记清除(Mark-Sweep)标记压缩(Mark-Compact)又称标记整理分代收集算法(Generational-Collection) 4.1. JVM复习 JVM结构图 堆内存结构 GC的特点 次数上频繁收集Young区次数上较少收集Old区基本不动Perm区 4.2. 垃圾判定 4.2.1. 引用计数法(Reference-Counting) 引用计数算法是通过判断对象的引用数量来决定对象是否可以被回收。 给对象中添加一个引用计数器每当有一个地方引用它时计数器值就加1当引用失效时计数器值就减1任何时刻计数器为0的对象就是不可能再被使用的。 优点 简单高效现在的objective-c、python等用的就是这种算法。 缺点 引用和去引用伴随着加减算法影响性能 很难处理循环引用相互引用的两个对象则无法释放。 因此目前主流的Java虚拟机都摒弃掉了这种算法。 4.2.2. 可达性分析算法 这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点从这些节点开始向下搜索节点所走过的路径称为引用链当一个对象到 GC Roots 没有任何引用链相连的话则证明此对象是不可用的。 在Java语言中可以作为GC Roots的对象包括下面几种 虚拟机栈栈帧中的本地变量表中的引用对象。方法区中的类静态属性引用的对象。方法区中的常量引用的对象。本地方法栈中JNINative方法的引用对象 真正标记以为对象为可回收状态至少要标记两次。 第一次标记不在 GC Roots 链中标记为可回收对象。 第二次标记判断当前对象是否实现了finalize() 方法如果没有实现则直接判定这个对象可以回收如果实现了就会先放入一个队列中。并由虚拟机建立一个低优先级的程序去执行它随后就会进行第二次小规模标记在这次被标记的对象就会真正被回收了 4.2.3. 四种引用 平时只会用到强引用和软引用。 强引用 ​ 类似于 Object obj new Object(); 只要强引用还存在垃圾收集器永远不会回收掉被引用的对象。 软引用 ​ SoftReference 类实现软引用。在系统要发生内存溢出异常之前才会将这些对象列进回收范围之中进行二次回收。如果这次回收还没有足够的内存才会抛出内存溢出异常。软引用可用来实现内存敏感的高速缓存。 弱引用 ​ WeakReference 类实现弱引用。对象只能生存到下一次垃圾收集之前。在垃圾收集器工作时无论内存是否足够都会回收掉只被弱引用关联的对象。 虚引用 ​ PhantomReference 类实现虚引用。无法通过虚引用获取一个对象的实例为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。 作用 虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于虚引用必须和引用队列 ReferenceQueue联合使用。当垃圾回收器准备回收一个对象时如果发现它还有虚引用就会在回收对象的内存之前把这个虚引用加入到与之 关联的引用队列中。你声明虚引用的时候是要传入一个queue的。当你的虚引用所引用的对象已经执行完finalize函数的时候就会把对象加到queue里面。你可以通过判断queue里面是不是有对象来判断你的对象是不是要被回收了 4.3. 垃圾回收算法 在介绍JVM垃圾回收算法前先介绍一个概念Stop-the-World Stop-the-world意味着 JVM由于要执行GC而停止了应用程序的执行并且这种情形会在任何一种GC算法中发生。当Stop-the-world发生时除了GC所需的线程以外所有线程都处于等待状态直到GC任务完成。事实上GC优化很多时候就是指减少Stop-the-world发生的时间从而使系统具有高吞吐 、低停顿的特点。 4.3.1. 复制算法(Copying) 该算法将内存平均分成两部分然后每次只使用其中的一部分当这部分内存满的时候将内存中所有存活的对象复制到另一个内存中然后将之前的内存清空只使用这部分内存循环下去。 优点 实现简单不产生内存碎片 缺点 将内存缩小为原来的一半浪费了一半的内存空间代价太高如果不想浪费一半的空间就需要有额外的空间进行分配担保以应对被使用的内存中所有对象都100%存活的极端情况所以在老年代一般不能直接选用这种算法。 如果对象的存活率很高我们可以极端一点假设是100%存活那么我们需要将所有对象都复制一遍并将所有引用地址重置一遍。复制这一工作所花费的时间在对象存活率达到一定程度时将会变的不可忽视。 所以从以上描述不难看出复制算法要想使用最起码对象的存活率要非常低才行而且最重要的是我们必须要克服50%内存的浪费。 年轻代中使用的是Minor GC这种GC算法采用的是复制算法(Copying)。 ​ HotSpot JVM把年轻代分为了三部分1个Eden区和2个Survivor区分别叫from和to。默认比例为8:1:1,一般情况下新创建的对象都会被分配到Eden区。因为年轻代中的对象基本都是朝生夕死的(90%以上)所以在年轻代的垃圾回收算法使用的是复制算法。 ​ 在GC开始的时候对象只会存在于Eden区和名为“From”的Survivor区Survivor区“To”是空的。紧接着进行GCEden区中所有存活的对象都会被复制到“To”而在“From”区中仍存活的对象会根据他们的年龄值来决定去向。对象在Survivor区中每熬过一次Minor GC年龄就会增加1岁。年龄达到一定值(年龄阈值可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中没有达到阈值的对象会被复制到“To”区域。经过这次GC后Eden区和From区已经被清空。这个时候“From”和“To”会交换他们的角色也就是新的“To”就是上次GC前的“From”新的“From”就是上次GC前的“To”。不管怎样都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程直到“To”区被填满“To”区被填满之后会将所有对象移动到年老代中。 因为Eden区对象一般存活率较低一般的使用两块10%的内存作为空闲和活动区间而另外80%的内存则是用来给新建对象分配内存的。一旦发生GC将10%的from活动区间与另外80%中存活的eden对象转移到10%的to空闲区间接下来将之前90%的内存全部释放以此类推。 4.3.2. 标记清除(Mark-Sweep) “标记-清除”(Mark Sweep)算法是几种GC算法中最基础的算法是因为后续的收集算法都是基于这种思路并对其不足进行改进而得到的。正如名字一样算法分为2个阶段 标记出需要回收的对象使用的标记算法均为可达性分析算法。 回收被标记的对象。 缺点 效率问题两次遍历 空间问题标记清除后会产生大量不连续的碎片。JVM就不得不维持一个内存的空闲列表这又是一种开销。而且在分配数组对象的时候寻找连续的内存空间会不太好找。 4.3.3. 标记压缩(Mark-Compact) 标记-整理法是标记-清除法的一个改进版。同样在标记阶段该算法也将所有对象标记为存活和死亡两种状态不同的是在第二个阶段该算法并没有直接对死亡的对象进行清理而是通过所有存活对像都向一端移动然后直接清除边界以外的内存。 优点 ​ 标记/整理算法不仅可以弥补标记/清除算法当中内存区域分散的缺点也消除了复制算法当中内存减半的高额代价。 缺点 ​ 如果存活的对象过多整理阶段将会执行较多复制操作导致算法效率降低。 老年代一般是由标记清除或者是标记清除与标记整理的混合实现。 4.3.4. 分代收集算法(Generational-Collection) 内存效率复制算法标记清除算法标记整理算法此处的效率只是简单的对比时间复杂度实际情况不一定如此。 内存整齐度复制算法标记整理算法标记清除算法。 内存利用率标记整理算法标记清除算法复制算法。 可以看出效率上来说复制算法是当之无愧的老大但是却浪费了太多内存而为了尽量兼顾上面所提到的三个指标标记/整理算法相对来说更平滑一些但效率上依然不尽如人意它比复制算法多了一个标记的阶段又比标记/清除多了一个整理内存的过程 难道就没有一种最优算法吗 回答无没有最好的算法只有最合适的算法。分代收集算法。 分代回收算法实际上是把复制算法和标记整理法的结合并不是真正一个新的算法一般分为老年代Old Generation和新生代Young Generation老年代就是很少垃圾需要进行回收的新生代就是有很多的内存空间需要回收所以不同代就采用不同的回收算法以此来达到高效的回收算法。 年轻代(Young Gen) ​ 年轻代特点是区域相对老年代较小对像存活率低。 ​ 这种情况复制算法的回收整理速度是最快的。复制算法的效率只和当前存活对像大小有关因而很适用于年轻代的回收。而复制算法内存利用率不高的问题通过hotspot中的两个survivor的设计得到缓解。 老年代(Tenure Gen) ​ 老年代的特点是区域较大对像存活率高。 ​ 这种情况存在大量存活率高的对像复制算法明显变得不合适。一般是由标记清除或者是标记清除与标记整理的混合实现。 4.4. 垃圾收集器了解 如果说收集算法是内存回收的方法论垃圾收集器就是内存回收的具体实现 4.4.1. Serial/Serial Old收集器 串行收集器是最古老最稳定以及效率高的收集器可能会产生较长的停顿只使用一个线程去回收。新生代、老年代使用串行回收新生代复制算法、老年代标记-压缩垃圾收集的过程中会Stop The World服务暂停 它还有对应老年代的版本Serial Old 参数控制 -XX:UseSerialGC 串行收集器 4.4.2. ParNew 收集器 ParNew收集器收集器其实就是Serial收集器的多线程版本除了使用多线程进行垃圾收集之外其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The world、对象分配规则、回收策略等都与Serial收集器完全一样实现上这两种收集器也共用了相当多的代码。ParNew收集器的工作过程如下图所示。 ParNew收集器 ParNew收集器其实就是Serial收集器的多线程版本。新生代并行老年代串行新生代复制算法、老年代标记-压缩 参数控制 -XX:UseParNewGC ParNew收集器 -XX:ParallelGCThreads 限制线程数量 4.4.3. Parallel / Parallel Old 收集器 Parallel Scavenge收集器类似ParNew收集器Parallel收集器更关注系统的吞吐量。可以通过参数来打开自适应调节策略虚拟机会根据当前系统的运行情况收集性能监控信息动态调整这些参数以提供最合适的停顿时间或最大的吞吐量也可以通过参数控制GC的时间不大于多少毫秒或者比例新生代复制算法、老年代标记-压缩 参数控制 -XX:UseParallelGC 使用Parallel收集器 老年代串行 Parallel Old是Parallel Scavenge收集器的老年代版本使用多线程和“标记整理”算法。这个收集器是在JDK 1.6中才开始提供 参数控制 -XX:UseParallelOldGC 使用Parallel收集器 老年代并行 4.4.4. CMS收集器 CMSConcurrent Mark Sweep收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用都集中在互联网站或B/S系统的服务端上这类应用尤其重视服务的响应速度希望系统停顿时间最短以给用户带来较好的体验。 从名字包含“Mark Sweep”上就可以看出CMS收集器是基于“标记-清除”算法实现的它的运作过程相对于前面几种收集器来说要更复杂一些整个过程分为4个步骤包括 初始标记CMS initial mark并发标记CMS concurrent mark重新标记CMS remark并发清除CMS concurrent sweep 其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象速度很快并发标记阶段就是进行GC Roots Tracing的过程而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录这个阶段的停顿时间一般会比初始标记阶段稍长一些但远比并发标记的时间短。 由于整个过程中耗时最长的并发标记和并发清除过程中收集器线程都可以与用户线程一起工作所以总体上来说CMS收集器的内存回收过程是与用户线程一起并发地执行。老年代收集器新生代使用ParNew 优点: 并发收集、低停顿 缺点: 产生大量空间碎片、并发阶段会降低吞吐量 参数控制 -XX:UseConcMarkSweepGC 使用CMS收集器 -XX: UseCMSCompactAtFullCollection Full GC后进行一次碎片整理整理过程是独占的会引起停顿时间变长 -XX:CMSFullGCsBeforeCompaction 设置进行几次Full GC后进行一次碎片整理 -XX:ParallelCMSThreads 设定CMS的线程数量一般情况约等于可用CPU数量 cms是一种预处理垃圾回收器它不能等到old内存用尽时回收需要在内存用尽前完成回收操作否则会导致并发回收失败 4.4.5. G1收集器 G1是目前技术发展的最前沿成果之一HotSpot开发团队赋予它的使命是未来可以替换掉JDK1.5中发布的CMS收集器。与CMS收集器相比G1收集器有以下特点 并行与并发G1能充分利用CPU、多核环境下的硬件优势使用多个CPUCPU或者CPU核心来缩短stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程执行的GC动作G1收集器仍然可以通过并发的方式让java程序继续执行。 分代收集分代概念在G1中依然得以保留。虽然G1可以不需要其它收集器配合就能独立管理整个GC堆但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。也就是说G1可以自己管理新生代和老年代了。 空间整合由于G1使用了独立区域Region概念G1从整体来看是基于“标记-整理”算法实现收集从局部两个Region上来看是基于“复制”算法实现的但无论如何这两种算法都意味着G1运作期间不会产生内存空间碎片。 可预测的停顿这是G1相对于CMS的另一大优势降低停顿时间是G1和CMS共同的关注点但G1除了追求低停顿外还能建立可预测的停顿时间模型能让使用这明确指定一个长度为M毫秒的时间片段内消耗在垃圾收集上的时间不得超过N毫秒。 上面提到的垃圾收集器收集的范围都是整个新生代或者老年代而G1不再是这样。使用G1收集器时Java堆的内存布局与其他收集器有很大差别它将整个Java堆划分为多个大小相等的独立区域Region虽然还保留有新生代和老年代的概念但新生代和老年代不再是物理隔阂了它们都是一部分可以不连续Region的集合。 每个Region被标记了E、S、O和H说明每个Region在运行时都充当了一种角色其中H是以往算法中没有的它代表Humongous这表示这些Region存储的是巨型对象humongous objectH-obj当新建对象大小超过Region大小一半时直接在新的一个或多个连续Region中分配并标记为H。 为了避免全堆扫描G1使用了Remembered Set来管理相关的对象引用信息。当进行内存回收时在GC根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏了。 如果不计算维护Remembered Set的操作G1收集器的运作大致可划分为以下几个步骤 1、初始标记Initial Making 2、并发标记Concurrent Marking 3、最终标记Final Marking 4、筛选回收Live Data Counting and Evacuation 看上去跟CMS收集器的运作过程有几分相似不过确实也这样。初始阶段仅仅只是标记一下GC Roots能直接关联到的对象并且修改TAMSNext Top Mark Start的值让下一阶段用户程序并发运行时能在正确可以用的Region中创建新对象这个阶段需要停顿线程但耗时很短。并发标记阶段是从GC Roots开始对堆中对象进行可达性分析找出存活对象这一阶段耗时较长但能与用户线程并发运行。而最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中这阶段需要停顿线程但可并行执行。最后筛选回收阶段首先对各个Region的回收价值和成本进行排序根据用户所期望的GC停顿时间来制定回收计划这一过程同样是需要停顿线程的但Sun公司透露这个阶段其实也可以做到并发但考虑到停顿线程将大幅度提高收集效率所以选择停顿。下图为G1收集器运行示意图 4.4.6. 垃圾回收器比较 如果两个收集器之间存在连线则说明它们可以搭配使用。虚拟机所处的区域则表示它是属于新生代还是老年代收集器。 整堆收集器 G1 垃圾回收器选择策略 客户端程序 Serial Serial Old 吞吐率优先的服务端程序比如计算密集型 Parallel Scavenge Parallel Old 响应时间优先的服务端程序 ParNew CMS。 G1收集器是基于标记整理算法实现的不会产生空间碎片可以精确地控制停顿将堆划分为多个大小固定的独立区域并跟踪这些区域的垃圾堆积程度在后台维护一个优先列表每次根据允许的收集时间优先回收垃圾最多的区域Garbage First。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/927506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

coduck模拟赛一 补题报告 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

RippleNet: Propagating User Preferences on the Knowledge Graph for Recommender Systems

1.知识图谱嵌入的基本过程,为什么难以直观有效表达项目间的关系 1.1基本过程(知识图谱嵌入)构建三元组: 将知识图谱表示为(头实体h, 关系r, 尾实体t)集合。向量化建模: 为每个实体、关系分配可学习的向量/矩阵,常见…

特地拎出来的总结

这篇总结不太一样,为了纪念和我爸喋喋不休吵了近3h的时间和教训,用Deepseek共同完成 : 题目 T674176 T2-任务task 题目描述 时间限制: 2.0 秒 空间限制: 512 MiB 有 \(n\) 个任务,第 \(i\) 个任务需要占据 \([l_…

在线做漫画的网站wordpress多用户评论

文献计量学是指用数学和统计学的方法,定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体,注重量化的综合性知识体系。特别是,信息可视化技术手段和方法的运用,可直观的展示主题的研究发展历程、研究现状、研究…

漏洞赏金计划的困境:i915漏洞与ChromeOS、Intel赏金项目剖析

本文深入探讨了漏洞赏金计划存在的系统性问题,通过作者亲身经历的i915驱动漏洞案例,揭示了Google和Intel在处理安全漏洞报告过程中的沟通不畅、缺乏透明度等问题,并分析了漏洞赏金计划中权力失衡的根本原因。漏洞赏…

wordpress站名在哪改项目协同管理平台

在 Unix 环境下," 寄存器需要 xterm-clipboard feature 的 VIM 软件才能使用,具有这个 feature 的 VIM 可以安装 vim-gtk(包含gvim和vim),使用 gvim 可以正常调用 " 寄存器。

2025异型件厂家推荐:邯郸市烁燊紧固件,广泛应用于建筑、桥梁、机械、电力、交通等诸多领域

在现代工业体系中,异型件作为关键基础零部件,广泛应用于建筑、桥梁、机械、电力、交通等诸多领域。随着各行业的快速发展,对异型件的质量、性能和精度等方面提出了更高的要求。在这样的背景下,邯郸市烁燊紧固件有限…

C++设计模式之行为型模式:解释器模式(Interpreter) - 详解

C++设计模式之行为型模式:解释器模式(Interpreter) - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Cons…

免费的小程序模板网站做网站服务公司

一、 搜索算法 深度优先搜索和广度优先搜索是最暴力的图的搜索算法。算法的目标是,给定一张图,一对初始和终止节点,找到两节点之间的节点路径。(代码均是找到两个节点之间的路径) 广度优先搜索是一层一层搜索&#xf…

中国最大网站建设商网站生成器怎么做

python绑定项目 官方未提供python的封装绑定,直接调用执行文件 https://github.com/stlukey/whispercpp.py提供了源码和Cpython结合的绑定 https://github.com/zhujun1980/whispercpp_py提供了ctype方式的绑定,需要先make libwhisper.so Pybind11 bi…

dede视频网站宣城市住房和城乡建设局网站首页

关注公号【逆向通信猿】更精彩!!! 1. 构造编码器对象 采用MATLAB内置的comm.LDPCEncoder构造编码器对象,其中使用默认的校验矩阵,信息位长32400比特,码长64800比特,该校验矩阵中除第一行中1的个数为6个外,其余行中1的个数均为7;前12960列中1的个数为8,后32400列构成…

如何备份一个网站广西住建局

1. C/C++ IDE 安装Clion Nova和VsCode 2. 编译器 2.1 g++ 当程序比较小时,安装g++编译器进行编译,常用命令如下: // 安装g++ sudo apt-get install g++ // 默认生成a.out的可执行文件 g++ main.cpp // 生成其他名字的可执行文件 g++ main.cpp -o exe_name2.2 cmake 当…

网站开发一次性费用网站建设公司发展方向及趋势

2020年9月10日,亚马逊通技术服务(北京)有限公司(AWS中国)与毕马威企业咨询(中国)有限公司(毕马威中国)宣布已签署战略合作协议。 双方将充分利用各自的全球品牌影响力和资…

深入解析:PostgreSQL向量检索:pgvector入门指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网贷之家网站建设你访问的网站正在建设

以上问题在编译器中出现可以在编译器中最上面加入: #define_CRT_SECURE_NO_WARNINGS 或者将scanf修改为scanf_s 一定要在最上端!!!最上端!!!最上端加入!!! 虽…

Allow or block media autoplay in Firefox

https://support.mozilla.org/en-US/kb/block-autoplay

寺庙网站开发文案wordpress免费主题插件下载

前文:最近跟着DataWhale组队学习这一期“Sora原理与技术实战”,本篇博客主要是基于DataWhale成员、厦门大学平潭研究院杨知铮研究员分享的Sora技术原理详解课件内容以及参考网上一些博客资料整理而来(详见文末参考文献)&#xff0…

[WC2018] 即时战略

[WC2018] 即时战略分享一下全局平衡二叉树的做法。 先讲下部分分。 \(n\le 100,T\le 10000\) 从 \(1\) 开始 DFS,对于当前 \(u\),枚举点 \(v\),如果 \(\text{explore}(u,v)\) 不为 \(fa_u\),则 \(v\) 为 \(u\) 子结…

商城网站源码大全微网站建站

怎么解决java导出excel时文件名乱码发布时间:2020-06-19 16:59:00来源:亿速云阅读:137作者:元一java解决导出Excel时文件名乱码的方法示例:String agent request.getHeader("USER-AGENT").toLowerCase();re…

实用指南:Unity学习之C#的反射机制

实用指南:Unity学习之C#的反射机制pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco…