jvm总结 矫情吗;* 2022-05-20 05:13 178阅读 0赞 # 一、JVM结构 # JVM是可运行Java代码的假想计算机 ![70][] ## 1.1 类加载器 ## ## 1.2 执行引擎:执行包在装载类的方法中的指令,也就是方法,class文件是否可运行,由执行引擎决定 ## ## 1.3 本地库接口:融合不同的编程语言为Java所用 ## ## 1.4 运行数据区 ## **1.4.1 ****本地方法栈**:登记native方法,在Execution Engine执行时加载native libraies **1.4.2 ****程序计数器**:每个线程都有一个程序计算器,就是一个指针,指向下一个将要执行的指令代码,由执行引擎读取下一条指令 **1.4.3 ****方法区**:线程共享,存储静态变量、常量、类信息、编译后的字节码 **1.4.4 ****栈**:线程私有。主管Java程序的运行。生命周期和线程一致,随线程创建时创建,线程结束栈内存释放,不存在垃圾回收问题。 1)存储:基本类型的变量和对象的引用变量 2)原理:栈中的数据都是以栈帧(Stack Frame)的格式存在,帧用来存储方法的参数、局部变量和运算过程中的临时数据。当一个方法A被调用时就产生了一 个栈帧F1,并被压入到栈中,A方法又调用了B方法,于是产生栈帧F2也被压入栈,B方法又调用了C方法,于是产生栈帧F3也被压入 栈…… 依次执行完毕后,先弹出后进......F3栈帧,再弹出F2栈帧,再弹出F1栈帧。遵循“先进后出”/“后进先出”原则。 **1.4.5 堆:**线程共享。jvm区域最大。一个jvm实例只存在一个堆类存,存储初始化对象,成员变量 1.4.5.1 新生区:类的诞生、成长、消亡的区域。分为伊甸区和幸存区(分为from区、to区) 1.4.5.2 养老区:保存从新生区筛选出来的 JAVA 对象 1.4.5.3 永久区:存放JDK自身所携带的 Class,Interface 的元数据。垃圾回收主要两部分内容:废弃的常量和无用的类 注意 :Jdk1.6及之前:常量池分配在永久代 。 Jdk1.7:有,但已经逐步“去永久代” 。 Jdk1.8及之后:无(java.lang.OutOfMemoryError: PermGen space,这种错误将不会出现在JDK1.8中),采用了Metaspace # 二、类加载机制 # ## 2.1 类加载过程 ## 2.2.1 加载:通过全限定名来加载生成class对象到内存中 2.2.2 验证:验证这个class文件,包括文件格式校验、元数据验证,字节码校验等 2.2.3 准备:分配内存,为类变量分配(被static修饰的变量,不包括实例变量,实例变量在对象实例化阶段分配)并设置类变量初始值的阶段,假如public static int value = 123;在准备阶段过后的初始值为0而不是123 2.2.4 解析:将符号引用转化为直接引用(指针引用) 2.2.5 初始化:为类的静态变量赋予正确的初始值,上述的准备阶段为静态变量赋予的是虚拟机默认的初始值,此处赋予的才是程序编写者为变量分配的真正的初始值 ** 主动引用(会发生初始化):** 1. 遇到new、getstatic、putstatic、invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。比如以下几种场景:1)、new对象 2)、调用类中的静态成员,除final 3)、调用类中的静态方法 2. 使用java.lang.reflect包的方法对类进行反射调用的时候,例如通过调用java.lang.Class.forName(String className) 3. 当初始化一个类的时候,如果发现其父类还没进行过初始化,则需要先触发其父类的初始化 4. 当虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先初始化这个主类。 其实就是public static void main(String\[\] args)所在的那个类 。 **被动应用(看上去会,其实不会发生初始化):** 1. 通过子类引用父类的静态字段,不会导致子类初始化; 2. 通过数组定义类引用类,不会触发此类的初始化; 3. 静态常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化 ## 2.2 双亲委派模型 ## 2.2.1 概念:一个类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载 2.2.2 优点:例如类java.lang.Object,它存在在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱 2.2.3 类加载器 1. Bootstrap ClassLoader:启动类加载器,负责将$ Java\_Home/lib下面的类库加载到内存中(比如rt.jar) 2. Extension ClassLoader:标准扩展(Extension)类加载器,它负责将$Java\_Home /lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中 3. ApplicationClassLoader:它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器 ## 2.3 java反射中,Class.forName和classloader的区别 ## java中class.forName()和classLoader都可用来对类进行加载。class.forName()前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。而classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static代码块和static方法 # 三、垃圾回收 # 在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中 3.1 GC判定方法 1)引用计数法:指的是如果某个地方引用了这个对象就+1,如果失效了就-1,当为0就会回收但是JVM没有用这种方式,因为无法判定相互循环引用(A引用B,B引用A)的情况 2)根搜索算法:通过一种GC ROOT的对象来判断,如果有一条链能够到达GC ROOT就说明,不能到达GC ROOT就说明可以回收 可以作为GC ROOT的对象有: 1、栈(栈帧中的本地变量表)中引用的对象。 2、方法区中的静态成员。 3、方法区中的常量引用的对象(全局变量) 4、本地方法栈中JNI(一般说的Native方法)引用的对象。 ### 3.2 GC收集方法 ### 1)标记清除:效率不高,会产生碎片 2)复制算法:解决标记清除效率问题,采用8:1的Eden区和survivor区(伊甸区98%对象会死去,没必要1:1),其中Eden和一块Survivor空间用来存放新生代的对象,还有一块用来复制垃圾回收时Eden和另外一块Survivor的存活对象 3)标记整理:解决标记清除算法的内存碎片问题,清理完可回收的对象后会对该内存块进行整理 4)分代收集算法:新生代采用复制算法,老年代采用“标记-清除”或者“标记-整理”算法 它们的区别如下:(>表示前者要优于后者,=表示两者效果一样) (1)效率:复制算法>标记/整理算法>标记/清除算法(此处的效率只是简单的对比时间复杂度,实际情况不一定如此)。 (2)内存整齐度:复制算法=标记/整理算法>标记/清除算法。 (3)内存利用率:标记/整理算法=标记/清除算法>复制算法。 ### 3.3 垃圾收集器 ### ** 3.3.1 新生代的垃圾收集器** 1) Serial收集器(复制算法):缺点是垃圾收集器回暂停用户的所有线程来进行单线程的垃圾收集 2) ParNew收集器(复制算法):Serial的多线程版本,默认开启的线程=CPU核心数,通过使用-XX:ParallelGCThreads参数可以来限制垃圾收集的线程数 3)Parallel Scavenge收集器(复制算法):跟parNew收集器差不多,但与上面2个收集器的关注点不同,前面的2个更多的关注用户的停顿时间,而此收集器更关注CPU的吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)。其中有2个参数可以控制这个吞吐量,1、-XX:MaxGCPauseMillis xxxx,控制最大垃圾收集停顿时间(x>0的毫秒数)。2、-XX:GCTimeRatio XXX,设置吞吐量大小(设置一个0<x<100的整数,表示垃圾收集器时间占总时间的比率,相当于吞吐量的倒数)。 另外,此收集器还有一个参数-XX:+UseAdaptiveSizePolicy,如果打开这个开发,则新生代的大小(-Xmn)、Eden、Survivor(-XX:SurvivorRatio)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等参数就不需要手工指定了,虚拟机会根据系统的运行情况来动态调整。 **3.3.2 老年代收集器** 1、Serial Old收集器(标记-整理算法):新生代serial的老年代版本,主要有如下2个用途:1、在JDK1.5以及之前的版本搭配新生代的Parallel Scavenge收集器使用。2、作为CMS收集器发生Concurrent Mode Failure的一个后备方案 2.Parallel Old收集器(标记-整理算法):新生代Parallel Scavenge收集器的老年代版本,在JDK1.6的版本中才提供,只能和新生代的Parallel Scavenge收集器搭配使用 3.CMS收集器(标记-清除算法):响应优先。分为初始标记、并发标记、重新标记、并发清除四个过程 优点:以获取最短回收停顿时间为目标的收集器,具有并发低顿挫的特点 缺点:1)对CPU资源很敏感(需要跟用户线程并发执行) 2)无法处理浮动垃圾(Floating Garbage,在标记过程后产生的垃圾),CMS需要预留足够的内存空间给用户线程使用,所以CMS收集器在老年代使用了68%的空间后被激活(可以通过-XX:CMSInitiatingOccupancyFranction参数来配置触发百分比),如果在运行过程中预留的内存无法满足程序需要,则会出现一次“Concurrent Mode Failure”失败并启用后备预案(Serial Old收集器)进行Full GC 3)采用标记-清除算法,会产生内存碎片,不过可以配置-XX:+UseCMSCompactAtFullCollection开关让Full GC后进行一次碎片整理,也可以使用-XX:CMSFullGCsBeforeCompaction来设置执行多少次Full GC自动来一次碎片整理。 4.G1收集器:吞吐量优先。在JDK1.6\_update14提供试用,是一款面向服务器应用的垃圾收集器 特点:1)并发运行 2)基于标记-整理算法,不会产生空间碎片 3)非常精确的控制停顿,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在收集上的时间不超过N毫秒 4)将整个堆(新生代、老年代)划分为多个大小固定的独立区域,并与这些区域为单位进行垃圾回收,避免对整个堆进行全量回收操作,并对这些区域进行优先级维护和回收 # 四、JVM调优 # ## 4.1 常用参数设置: ## **4.1.1 堆设置** * \-Xmx3550m:设置JVM**最大堆内存**为3550M。 * \-Xms3550m:设置JVM**初始堆内存**为3550M。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。 * \-Xss128k:设置每个线程的栈大小。JDK5.0以后每个线程栈大小为1M,之前每个线程栈大小为256K。应当根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。需要注意的是:当这个值被设置的较大(例如>2MB)时将会在很大程度上降低系统的性能。 * \-Xmn2g:设置**年轻代**大小为2G。在整个堆内存大小确定的情况下,增大年轻代将会减小年老代,反之亦然。此值关系到JVM垃圾回收,对系统性能影响较大,官方推荐配置为整个堆大小的3/8。 * \-XX:NewSize=1024m:设置年轻代初始值为1024M。 * \-XX:MaxNewSize=1024m:设置年轻代最大值为1024M。 * \-XX:PermSize=256m:设置**持久代初始值**为256M。 * \-XX:MaxPermSize=256m:设置**持久代最大值**为256M。 * \-XX:NewRatio=4:设置年轻代(包括1个Eden和2个Survivor区)与年老代的比值。表示年轻代比年老代为1:4。 * \-XX:SurvivorRatio=4:设置**年轻代中Eden区与Survivor区的比值**。表示2个Survivor区(JVM堆内存年轻代中默认有2个大小相等的Survivor区)与1个Eden区的比值为2:4,即1个Survivor区占整个年轻代大小的1/6。 * \-XX:MaxTenuringThreshold=7:表示一个对象如果在Survivor区(救助空间)移动了7次还没有被垃圾回收就进入年老代。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代,对于需要大量常驻内存的应用,这样做可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代存活时间,增加对象在年轻代被垃圾回收的概率,减少Full GC的频率,这样做可以在某种程度上提高服务稳定性。 疑问解答:-Xmn,-XX:NewSize/-XX:MaxNewSize,-XX:NewRatio 3组参数都可以影响年轻代的大小,混合使用的情况下,优先级是什么? 如下: 1. 高优先级:-XX:NewSize/-XX:MaxNewSize 2. 中优先级:-Xmn(默认等效 -Xmn=-XX:NewSize=-XX:MaxNewSize=?) 3. 低优先级:-XX:NewRatio 推荐使用-Xmn参数,原因是这个参数简洁,相当于一次设定 NewSize/MaxNewSIze,而且两者相等,适用于生产环境。-Xmn 配合 -Xms/-Xmx,即可将堆内存布局完成。 \-Xmn参数是在JDK 1.4 开始支持。 ** 4.1.2 收集器设置** -XX:+UseSerialGC:设置串行收集器 -XX:+UseParallelGC:设置并行收集器 -XX:+UseParalledlOldGC:设置并行年老代收集器 -XX:+UseConcMarkSweepGC:设置并发收集器 并行收集器设置 \-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。 \-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间 \-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) 并发收集器设置 \-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。 \-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。 ** 4.1.3 垃圾回收统计信息** -XX:+PrintGC:输出形式:\[GC 118250K->113543K(130112K), 0.0094143 secs\] \[Full GC 121376K->10414K(130112K), 0.0650971 secs\] -XX:+PrintGCDetails:输出形式:\[GC \[DefNew: 8614K->781K(9088K), 0.0123035 secs\] 118250K->113543K(130112K), 0.0124633 secs\] \[GC \[DefNew: 8614K->8614K(9088K), 0.0000665 secs\]\[Tenured: 112761K->10414K(121024K), 0.0433488 secs\] 121376K->10414K(130112K), 0.0436268 secs\] -XX:+PrintGCTimeStamps:可与上面两个混合使用,输出形式:11.851: \[GC 98328K->93620K(130112K), 0.0082960 secs\] -Xloggc:filename:把相关日志信息记录到文件以便分 ## 4.2 调优总结 ## 年轻代大小选择 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。 养老代大小选择 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得: 1. 并发垃圾收集信息 2. 持久代并发收集次数 3. 传统GC信息 4. 花在年轻代和年老代回收上的时间比例 减少年轻代和年老代花费的时间,一般会提高应用的效率 吞吐量优先的应用 一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。 较小堆引起的碎片问题 因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置: 1. -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。 2. -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩 案例一:大型网站服务器案例 承受海量访问的动态Web应用 服务器配置:8 CPU, 8G MEM, JDK 1.6.X 参数方案: \-server -Xmx3550m -Xms3550m -Xmn1256m -Xss128k -XX:SurvivorRatio=6 -XX:MaxPermSize=256m -XX:ParallelGCThreads=8 -XX:MaxTenuringThreshold=0 -XX:+UseConcMarkSweepGC 案例二:内部集成构建服务器案例 高性能数据处理的工具应用 服务器配置:1 CPU, 4G MEM, JDK 1.6.X 参数方案: \-server -XX:PermSize=196m -XX:MaxPermSize=196m -Xmn320m -Xms768m -Xmx1024m ## 4.3 调试工具 ## 常用的几种内存调试工具(jdk自带,位于bin目录下):jmap、jstack、jconsole、jhat 详情访问 [https://blog.csdn.net/qq\_33314107/article/details/81045318 ][https_blog.csdn.net_qq_33314107_article_details_81045318] ## 五、问题总结 ## # 1、进入老年代的几种途径 # 1)、在新生代GC过程中survivor空间不够,通过老年代的分配担保机制提前转入老年代。 2)、超过参数PretenureSizThreshold设置的值的大对象直接进入老年代,所谓大对象就是需要大量连续内存空间的java对象(例如很长的字符串和大数组)。 3)、长期存活的新生代对象进入老年代,如果对象在一次Minor GC(新生代GC)后仍存活并且能被survivor容纳后被移动到Survivor中后将该对象的年龄+1,当它的年龄达到一定程 度(默认15)后就会晋升到老年代,这个阀值可以通过-XX:MaxTenuringThreshold来设置。 4)、虚拟机并不总要求对象达到XX:MaxTenuringThreshold的值后才晋升老年代,如果在Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于或者等于 该年龄的对象就可以直接进入老年代。 2、 如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二: a.Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。 b.代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。 如果出现java.lang.OutOfMemoryError: PermGen space,说明是Java虚拟机对永久代Perm内存设置不够。原因有二: a. 程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。 b. 大量动态反射生成的类不断被加载,最终导致Perm区被占满。 3、几种常用的内存调试工具:jmap、jstack、jconsole、jhat;例如当出现了内存溢出时,可以用jmap看内存情况,然后用 jstack主要用来查看某个Java进程内的线程堆栈信息 4.分派:分派是**多态性**的体现。分为静态分派、动态分派。重载属于静态分派,重写属于动态分派 5. g1和cms区别,吞吐量优先和响应优先的垃圾收集器选择 CMS收集器:一款以获取最短回收停顿时间为目标的收集器,是基于“标记-清除”算法实现的,分为4个步骤:初始标记、并发标记、重新标记、并发清除。 G1收集器:面向服务端应用的垃圾收集器,过程:初始标记;并发标记;最终标记;筛选回收。整体上看是“标记-整理”,局部看是“复制”,不会产生内存碎片。 吞吐量优先的并行收集器:以到达一定的吞吐量为目标,适用于科学技术和后台处理等。 响应时间优先的并发收集器:保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。 6. 说一说你对环境变量classpath的理解?如果一个类不在classpath下,为什么会抛出ClassNotFoundException异常,如果在不改变这个类路径的前期下,怎样才能正确加载这个类? classpath是javac编译器的一个环境变量。它的作用与import、package关键字有关。package的所在位置,就是设置CLASSPATH当编译器面对import packag这个语句时,它先会查找CLASSPATH所指定的目录,并检视子目录java/util是否存在,然后找出名称吻合的已编译文件(.class文件)。如果没有找到就会报错! 动态加载包 7.内存溢出和内存泄漏的区别: 内存溢出:是指内存不足 内存泄漏:是指无法释放已申请的内存空间 8.java对象的四种引用: 1)强引用:创建一个对象并把这个对象赋给一个引用变量, 只要强引用还在,永远不会回收 public class Main { public static void main(String[] args) { new Main().fun1(); } //语句1、2、3都属于强引用,当程序运行到语句3,内存不过时,jvm会抛出oom异常,不会垃圾回收,只有fun1()方法运行完,才可以回收。 可以设置值为null,jvm会在合适的时间回收 public void fun1() { Object object = new Object(); //语句1 Object object = "fdfdfd"; //语句2 Object[] objArr = new Object[1000]; //语句3 } 2)软引用:非必需对象。内存不足时,进行回收 。主要用于缓存 MyObject aRef = new MyObject(); //强引用 ReferenceQueue queue = new ReferenceQueue(); //用来管理SoftReference对象,避免大量SoftReference对象回收之后带来的内存泄漏 SoftReference aSoftRef=new SoftReference(aRef,queue); //软引用 aRef =null; aRef =aSoftRef.get();//在垃圾回收aSoftRef对象时,SoftReference类所提供的get()方法返回Java对象的强引用。回收之后,返回null 3)弱引用:非必须对象。只要jvm进行垃圾回收,就会回收被弱引用的对象。 public class test { public static void main(String[] args) { WeakReference<People>reference=new WeakReference<People>(new Strinng("zhouqian"));//这里也可以跟ReferenceQueue结合使用 //String str =new Strinng("zhouqian"); //语句1 //WeakReference<People>reference=new WeakReference<People>(str); //语句2 System.out.println(reference.get()); //返回zhouqian System.gc();//通知GVM回收资源 System.out.println(reference.get()); //返回null } 假设是语句1和语句2这种写法,弱引用和强引用结合,被引用对象不会被回收,返回都是zhouqian } 4)虚引用:在任何时候都可能被垃圾回收器回收。 import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; public class Main { public static void main(String[] args) { ReferenceQueue<String> queue = new ReferenceQueue<String>(); PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue); System.out.println(pr.get()); //通过get()方法,得到的永远是null } //虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收 } [70]: /images/20220520/6b4a1ed455ca4ad6ac45992f67868696.png [https_blog.csdn.net_qq_33314107_article_details_81045318]: https://blog.csdn.net/qq_33314107/article/details/81045318
相关 jvm总结 *目录** 1、什么情况下会发生堆、栈内存溢出。 2、JVM的内存结构,Eden和Survivor比例。 3、JVM内存为什么要分成新生代,老年代,持久代。新生代中... 刺骨的言语ヽ痛彻心扉/ 2024年04月17日 05:48/ 0 赞/ 79 阅读
相关 JVM总结 目录 一,Java虚拟机 1.概念 2.作用 3.运行流程 二,运行时数据区域 理解线程私有 1.Java虚拟机栈(线程私有) 作用 栈帧的组成 2.本地 阳光穿透心脏的1/2处/ 2023年09月30日 13:13/ 0 赞/ 23 阅读
相关 JVM总结 常见面试题 请你谈谈你对JVM的理解? java8虚拟机和之前的变化和更新 什么是OOM?什么是栈溢出?怎么分析? JVM常见的调优参数有哪些? Dear 丶/ 2023年07月12日 14:08/ 0 赞/ 27 阅读
相关 jvm总结 学习JVM的目的也很简单: 能够知道JVM是什么,为我们干了什么,具体是怎么干的。能够理解到一些初学时不懂的东西 在面试的时候有谈资 能装逼 一、简单聊 一时失言乱红尘/ 2023年06月19日 07:19/ 0 赞/ 21 阅读
相关 JVM总结 目录 1.什么是JVM 2.JVM基本结构 3.运行时数据区 4 hotspot方法区的实现 5 堆的结构 6 为何新生代要设置两个survivor区 7 对象访 桃扇骨/ 2023年01月01日 06:51/ 0 赞/ 161 阅读
相关 jvm总结 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQy 旧城等待,/ 2022年12月27日 14:29/ 0 赞/ 206 阅读
相关 JVM 总结 [初期预调优][Link 1] JVM总结: 一、理论 一、JVM内存模型: 二、JVM垃圾回收机制(从新生代和老年代的角度分析): 三、JVM调优经历:[调优实战][ 向右看齐/ 2022年10月27日 12:17/ 0 赞/ 188 阅读
相关 JVM总结 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_Q1NETiBA5LiA54K55Y2a5a6i_ r囧r小猫/ 2022年09月08日 10:26/ 0 赞/ 177 阅读
相关 jvm总结 一、JVM结构 JVM是可运行Java代码的假想计算机 ![70][] 1.1 类加载器 1.2 执行引擎:执行包在装载类的方法中的指令,也就是方法,clas 矫情吗;*/ 2022年05月20日 05:13/ 0 赞/ 179 阅读
还没有评论,来说两句吧...