问题:请你谈谈你认识几种 JVM?(3种)
问题:jvm除了Service模式是否有Client模式?他们有什么区别?如何修改?(了解即可)
Server模式启动时,速度较慢,但是一旦运行起来后,性能将会有很大的提升(64位系统默认)
Client模式启动时,启动较快,占用内存少,针对客户端进行优化(32位系统默认,一般用不到)
在路径JAVA_HOME/jre/lib/amd64/jvm.cfg 修改-server和-client的配置即可完成更改。
问题:jvm有几种mode?如何修改?(了解即可)
-Xmixed
-Xint
-Xcomp
称为启动类加载器,处于加载器的最顶层,负责加载rt.jar、resources.jar、charsets.jar等,由于是C写的所以java程序触及不到。
public class JvmDemo { |
称为扩展类加载器,父类是BootStrap ClassLoader,负责加载Java的扩展类库,Java 虚拟机会提供一个扩展库目录,该类加载器在此目录里面查找并加载 Java 类。默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。
public class JvmDemo { |
称为应用程序加载器,父类是Ext ClassLoader,负责加载我们自定义的类,是我们接触最多的加载器,加载classpath下面的类。
public class JvmDemo { |
双亲委派机制 可以保护java的核心类不会被自己定义的类所替代
一层一层的让父类去加载,如果顶层的加载器不能加载,然后再向下类推,直到某个类加载器覆盖到了为止。
加载.class文件
连接
在把java编译为class文件的时候,虚拟机并不知道所引用的地址;助记符:符号引用! |
静态变量赋予正确的值
当类被加载时,会执行的代码块:static{},从基类开始从上至下加载。
package vc.coding.jvm; |
当一个常量的值如果编译期间可以确定的,那这个值就会被加载到调用者类的常量池中!
package vc.coding.jvm; |
public class Test { |
每个线程都有一个程序计数器,是线程私有的。
程序计数器就是一块十分小的内存空间;几乎可以不计
作用: 当前字节码执行的行号指示器
分支、循环、跳转、异常处理!都需要依赖于程序计数器来完成!
bipush
将 int、float、String、常量值推送值栈顶
istore
将一个数值从操作数栈存储到局部变量表
iadd
加
imul
乘
对比队列来说
队列是吃多了拉 = 先进先出 = FIFO(First Input First OutPut)
栈是喝多了吐 = 后进先出 = LIFO (Last Input First OutPut)
栈是掌管程序运行的,毎执行一个命令就是往栈中压一层,直到最后上一层执行完毕之后就弹出,栈空了线程就Over了。
存储一些基本类型的值、对象的引用(引用指向堆内存)、方法等…
问:为什么java的方法传递是值传递而不是引用传递?
答:因为实参传递到方法形参的过程,就是把栈中对象的引用值(也可以理解为堆的地址)传递过去,形参同样会开辟栈空间存储这个引用。
public class Demo01 { |
栈帧
因为物理上不在堆中而逻辑上可以归为堆中(下面👇堆会提到),所以又称:非堆区(Non-Heap space)
Method Area 方法区 是 Java虚拟机规范中定义的运行数据区域之一,和堆(heap)一样可以在线程之间共享!
JDK1.7之前
永久代:用于存储一些虚拟机加载类信息,常量,字符串、静态变量等等。。这些东西都会放到永久代中;
永久代大小空间是有限的:如果满了 OutOfMemoryError:PermGen
JDK1.8之后
HotSpot jvm 中彻底将永久代移除,新增了 Meta Spaces (元空间)
元空间就是方法区在 HotSpot jvm 的实现;
方法区主要就是来存:类信息,常量,字符串、静态变量、符号引用、方法代码。。。
元空间和永久代最大的区别:元空间并不在Java虚拟机中,使用的是本地内存!
调整元空间大小:-XX:MetasapceSize10m
一个JVM实例只有一个堆,可供所有线程共享数据,堆的大小是可以调节的。
可以存储的内容:对象实例、类、方法、常量。
分为三个部分:
GC垃圾回收主要发生在新生区与养老区中,又分为普通GC和Full GC,如果堆满了,则会报出OOM异常(OutOfMemoryError)。
-Xmx:最大堆大小 (默认为系统内存的1/4)
-Xms:初始堆大小 (默认为系统内存的1/64)
-Xmn: 年轻代大小 (默认为堆的1/3)
新生区是一个对象诞生、成长、消亡的地方。
新生区的细分:Eden、s0与s1区(from to),所有的对象Eden被new出来,慢慢当Eden满了,程序还需要创建对象的时候,会触发一次轻量级的GC,清理完后将活下来的对象放入幸存者区(也就是s0与s1),毎执行一次轻GC就会将活着的对象在s0与s1中进行复制、交换、销毁(下面👇GC会详细解释)。
新生区中清理了很多次之后,如果有一些特别顽强的对象经历了15次垃圾回收(默认也是最大值15,可调参)!则送入养老区!
如果运行了很久之后,养老区也满了,就会触发Full GC。
存放类信息、方法、常量。
几乎不会被垃圾回收。
常量回收条件:当没有对象引用一个常量的时候,该常量即可以被回收。
对象回收条件:1.该类的实例都被回收。 2.加载该类的classLoader已经被回收 3.该类不能通过反射访问到其方法,而且该类的java.lang.class没有被引用 当满足这3个条件时,可以被回收。
方法区和堆一样,是共享的区域,是JVM 规范中的一个逻辑的部分,别名:非堆。
JDK1.6之前:有永久代、常量池在方法区;
JDK1.7:有永久代、但是尝试去永久代,常量池在堆中;
JDK1.8之后:永久代没有了,取而代之的是元空间:常量池在元空间中;
以 -
开头的为标配参数
在各种版本之间都很稳定,很少有变化
-X
开头的为标配参数-XX
开头的为标配参数-XX:+
开头代表开启某个功能,例如:-XX:+PrintGCDetails。-XX:-
开头代表关闭某个功能,例如:-XX:-PrintGCDetails。-XX:
key=value,例如:-XX:InitialHeapSize=268435456。参数 | 描述 |
---|---|
-verbose:class | 输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进行诊断。 |
-verbose:gc | 输出每次GC的相关情况。 |
-verbose:jni | 输出native方法调用的相关情况,一般用于诊断jni调用错误信息。 |
参数 | 描述 |
---|---|
-Xint | 解释执行 |
-XComp | 第一次使用就编译成本地的代码 |
-Xmixed | 混合模式(Java默认) |
-Xprof | 跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。 |
参数 | 描述 |
---|---|
-Xmx8m | 最大堆内存8m (-XX:InitialHeapSize=8m缩写) |
-Xms8m | 初始堆内存8m (-XX:MaxHeapSize=8m缩写) |
-Xmn200m | 设置年轻代大小为200M。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。(缩写语法糖) |
-Xss128k | 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。(缩写语法糖) |
-XX:+PrintGCDetails | 打印GC详情 |
-XX:+HeapDumpOnOutOfMemoryError | dump 内存溢出异常 |
-XX:MetaspaceSize=10m | 元空间大小=10m |
-XX:MaxMetaspaceSize=10m | 最大元空间大小=10m |
-XX:+TraceClassLoading | 跟踪类加载 |
-XX:MaxTenuringThreshold = 15 | 进入老年区的存活阈值 |
-XX:NewRatio=2 | 设置年轻代与老年代的占比:NewRatio = 2 新生代1,老年代是2,默认新生代整个堆的 1/3;NewRatio = 4 新生代1,老年代+是4,默认新生代整个堆的 1/5; |
-XX:+HeapDumpOnOutOfMemoryError
可以在内存溢出时,dump内存快照-XX:HeapDumpPath=目录+产生的时间.hprof
设置内存快照生成地址jps
命令:查看当前运行java进程
jconsole
进程号:查看java进程当前运行状况:
Jprofiler是一个强大的java程序监控软件,功能十分丰富!
Jprofiler官网下载安装: https://www.ej-technologies.com/products/jprofiler/overview.html
在IDEA 中绑定 JProfiler,则可在idea以Jprofiler监控的方式启动:
GC就是java中的垃圾回机制,一直在追求更快且高效的道路中。
随着应用程序所应对的业务越来越庞大、复杂,用户越来越多,没有GC就不能保证应用程序正常进行。而经常造成STW的GC又跟不上实际的需求,所以才会不断地尝试对GC进行优化
GC
」Full GC
」优点:不需要额外的空间!
缺点:两次扫描、耗时比较严重,并且会产生内存碎片,内存不连续!(如果再来存东西会多判断这个地址是否存的下)
优点:不需要额外的空间!无内存碎片!
缺点:耗时同样比较严重!
在我们这个要使用算法的空间中,假设这个空间中对象较少,不经常发生GC,那么可以考虑使用这个算法!
内存效率:复制算法 > 标记清除算法 > 标记压清除缩算法(时间复杂度)
内存整齐度:复制算法=标记清除压缩算法>标记清除算法
内存利用率:标记清除压缩算法 = 标记清除算法 > 复制算法
效率上来说复制算法最好,但是浪费空间较多!为了兼顾所有指标,标记清除压缩算法比较平滑,但是也不太完美!
难道没有一种最优的算法吗?
答案:没有!没有最好的只有最合适的!—–>分代收集算法:不同的区域使用不同的算法!
新生代:相对于老年代,存活率较低、GC次数较多、99%的对象在这里被清理、区域小!推荐使用:复制算法!
老年代:相对于新生代,存活率高、GC次数较少、区域比较大! 推荐使用:标记清除压缩算法!
什么是垃圾:简单来说,就是不再被引用的对象!
Person person = new Person(); |
如此可知每次发生GC时,上图A对象count=0,所以会被清理,而其他对象则不会被清理,这里有一个严重的问题,比如C与D对象是互相引用的关系,这两个对象可能永远无法被清理。
虚拟机栈中引用的对象。
在类中静态属性引用的对象。
在方法区中的常量。
本地方法栈中Native方法引用的对象(JNI了解即可)。
public class GCRoots{ |
STW:Stop the World:代表JVM准备GC时,所有的线程都停止!
-XX:MaxGCPauseMillis=100
调整最大的GC停顿时间单位:毫秒,JVM尽可能的保证停顿小于这个时间!G1的优点:
JDK7/8中,HotSpot虚拟机所有收集器及组合(连线),如下图:
图中一共有7中收集器
Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1。
它们每个收集器都有自己负责的区域:
java -XX:+PrintCommandLineFlags -version |
单CPU,单机程序,内存小。
-XX:+UseSerialGC
多CPU,大吞吐量,后台计算!
-XX:+UseParNewGC
多CPU,但是不希望有时间停顿,快速响应!
XX:+UseParallelGC
、-XX:+UseG1GC
摘自 《深入理解 Java 虚拟机》第二版 P90
参数 | 描述 |
---|---|
UseSerialGC | 虚拟机运行在Client模式下的默认值,打开此开关后,使用 Serial + Serial Old 的收集器组合进行内存回收 |
UseParNewGC | 打开此开关后,使用 ParNew + Serial Old 的收集器组合进行内存回收 |
UseConcMarkSweepGC | 使用 ParNew + CMS + Serial Old 的收集器组合进行内存回收。Serial Old 收集器将作为 CMS 收集器出现 Concurrent Mode Failure 失败后的后备收集器使用 |
UseParallelGC | 虚拟机运行在 Server 模式下的默认值, 使用 Parallel Scavenge + Serial Old(PS MarkSweep) 的收集器组合进行内存回收 |
UseParallelOleGC | 使用 Parallel Scavenge + Parallel Old 的收集器组合进行回收内存 |
ServivorRatio | 新生代中 Eden 区域与 Survivor 区域的容量比值,默认为8,代表 Eden : Survivor=8 : 1 |
PretenureSizeThreshold | 直接晋升老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配 |
MaxTenuringThreshold | 晋升到老年代的对象年龄。每个对象在坚持过一次 Minor GC 之后,年龄旧增加1,当超过这个参数值就进入老年代 |
UseAdaptiveSizePolicy | 动态调整 Java 堆中各个区域的大小以及进入老年代的年龄 |
HandlePromotionFailiure | 是否允许分配担保失败,即老年代的剩余空间不足以应付新生代的整个 Eden 和 Survivor 区的所有对象都存活的极端情况 |
ParallelGCThreads | 设置并行 GC 时进行内存回收的线程数 |
GCTimeRatio | GC 时间占总时间的比率,默认值为99,即允许1%的 GC 时间。仅在使用 Parallel Scavenge 收集时生效 |
MaxGCPauseMillis | 设置 GC 的最大停顿时间。仅在使用 Parallel Scavenge 收集器时生效 |
CMSInitiatingOccupancyFraction | 设置 CMS 收集器在老年代空间被使用多少后触发垃圾收集。默认值68%,尽在使用CMS 收集器时生效 |
UseCMSCompactAtFullCollection | 设置 CMS 收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅在使用 CMS 收集器时生效 |
CMSFullGCsBeforeCompaction | 设置 CMS 收集器在进行若干次垃圾收集后再启动一次内存碎片整理。仅在使用 CMS 收集器时生效 |
UseG1GC | 使用 G1 (Garbage First) 垃圾收集器 |
深圳SEO优化公司泰安高端网站设计多少钱沙井网站开发价格大鹏网站定制价格安康百度网站优化排名价格怒江关键词按天计费多少钱哈尔滨关键词按天扣费公司襄阳品牌网站设计哪家好崇左百搜标王哪家好钦州建设网站推荐邯郸网站推广工具多少钱日照网站制作红河建站推荐威海网站搭建公司芜湖网站搭建价格三明外贸网站设计哪家好绥化外贸网站制作公司景德镇SEO按天扣费哪家好惠州网站搜索优化多少钱三明网站改版报价山南高端网站设计报价枣庄营销型网站建设哪家好临夏SEO按天计费多少钱德宏网站建设价格泉州网站建设设计报价石家庄推广网站多少钱枣庄建设网站马鞍山百度关键词包年推广宝安建站公司海东seo网站推广价格韶关品牌网站设计多少钱歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运