1、内存模型(1.7 和1.8),每个区域做什么

jdk 1.8之前:
image.png
jdk 1.8之后:
image.png
两者区别:元空间取代了永久代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元数据空间并不在虚拟机中,而是使用本地内存
方法区、堆(运行是数据区在所有线程中共享)、本地方法栈、Java栈、程序计数器(私有)
方法区:它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆:Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
JVM栈:虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
本地方法栈:本地方法栈则是为虚拟机使用到的Native方法服务。
程序计数器:是当前线程所执行的字节码的行号指示器,执行到哪一行。

2、堆内存组成(新生代和老年代)

  1. ![](https://cdn.nlark.com/yuque/0/2021/png/12870696/1616232099800-8f995322-26f5-43c8-b19b-ffdaf822651c.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_17%2Ctext_Q29kaW5nU2ly5LiA5Liq5LiT5Lia55qESmF2YeW5sui0pw%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10%2Fresize%2Cw_599%2Climit_0#from=url&id=WtM6T&margin=%5Bobject%20Object%5D&originHeight=250&originWidth=599&originalType=binary&ratio=1&status=done&style=none)<br />a.新生代(Young):新生成的对象优先存放在新生代中,新生代对象朝生夕死,存活率很低。在新生代中,常规应用进行一次垃圾收集一般可以回收70% ~ 95% 的空间,回收效率很高。如果把新生代再分的细致一点,新生代又可细分为Eden空间、From Survivor空间、To Survivor空间,默认比例为8:1:1。<br />b.老年代(Tenured/Old):在新生代中经历了15次(具体看虚拟机配置的阀值)GC后仍然存活下来的对象会进入老年代中。老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢。<br />c.永久代(Perm):永久代存储类信息、常量、静态变量、即时编译器编译后的代码等数据,对这一区域而言,Java虚拟机规范指出可以不进行垃圾收集,一般而言不会进行垃圾回收。<br />其中新生代和老年代组成了Java堆的全部内存区域,而永久代不属于堆空间,它在JDK 1.8以前被Sun HotSpot虚拟机用作方法区的实现.

3、类的加载过程

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/22477832/1630503491718-b7c3d413-c96f-4fcd-b047-ceb83ec2eae6.png#clientId=u89aa6bd5-1193-4&from=paste&height=225&id=u37f4f6a5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=449&originWidth=1210&originalType=binary&ratio=1&size=144593&status=done&style=none&taskId=u25191309-b7e2-4c79-9906-ce022d3584b&width=605)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22477832/1630503872477-d6ee31d0-71d8-4919-9c26-7b68a854576a.png#clientId=u7ecaafc3-421f-4&from=paste&height=189&id=uedf8f924&margin=%5Bobject%20Object%5D&name=image.png&originHeight=324&originWidth=1216&originalType=binary&ratio=1&size=187995&status=done&style=none&taskId=uf4d8d999-db26-4eb8-b463-a1d274bc12d&width=711)

4、类加载器

Bootstrap ClassLoader(启动类加载器):Bootstrap ClassLoader,负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录,下 同)下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库
Extention ClassLoader(扩展类加载器) :Extension ClassLoader,该加载器由sun.misc.Launcher$ExtClassLoader实现,
它负责加载DK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如 javax.*开头的类),开发者可以直接使用扩展类加载器
App ClassLoader(应⽤类加载器):Application ClassLoader,该类加载器由 sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器

5、双亲委派模型?如何打破?

双亲委派机制的意思是除了顶层的启动类加载器以外,其余的类加载器,在加载之前,都会委派给它的
⽗加载器进⾏加载。这样⼀层层向上传递,直到祖先们都⽆法胜任,它才会真正的加载。为了保证内存内存不会有两份相同的字节码、保证核心.class不能被篡改。
image.png

6、内存溢出和内存泄漏

内存泄漏(memoryleak)是指应用程序在申请内存后,无法释放已经申请的内存空间,一次内存泄漏危害可以忽略,但如果任其发展最终会导致内存溢出( outofmemory)。如读取文件后流要进行及时的关闭以及对数据库连接的释放。
内存溢出(outofmemory)是指应用程序在申请内存时,没有足够的内存空间供其使用。如我们在项目中对于大批量数据的导入,采用分批量提交的方式。

7、JVM相关参数-调优

堆设置:
-Xms 初始堆大小,ms是memory start的简称 ,等价于-XX:InitialHeapSize
-Xmx 最大堆大小,mx是memory max的简称 ,等价于参数-XX:MaxHeapSize
-XX:NewSize=n 设置年轻代大小
-XX:NewRatio=n 设置年轻代和年老代的比值。如:-XX:NewRatio=3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4,默认新生代和老年代的比例=1:2。
-XX:SurvivorRatio=n 年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个,默认是8,表示
Eden:S0:S1=8:1:1
如:-XX:SurvivorRatio=3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5。
-XX:MaxPermSize=n 设置持久代大小,
-XX:MetaspaceSize 设置元空间大小 。
收集器设置:
-XX:+UseSerialGC 设置串行收集器
-XX:+UseParallelGC 设置并行收集器
-XX:+UseParalledlOldGC 设置并行年老代收集器
-XX:+UseConcMarkSweepGC 设置并发收集器
垃圾回收统计信息:
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename 日志输出到文件里filename,比如:-Xloggc:/gc.log
并行收集器设置:
-XX:ParallelGCThreads=n 设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n 设置并行收集最大暂停时间
-XX:GCTimeRatio=n 设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:MaxGCPauseMillis=n设置并行收集最大暂停时间
并发收集器配置:
-XX:+CMSIncrementalMode 设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n 设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

8、JVM相关的命令-调优

Sun JDK监控和故障处理命令有:jps jstat jmap jhat jstack jinfo
jps,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。
jstat,JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机
进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
jmap,JVM Memory Map命令用于生成heap dump文件
jhat,JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了
一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看
jstack,用于生成java虚拟机当前时刻的线程快照。
jinfo,JVM Confifiguration info 这个命令作用是实时查看和调整虚拟机运行参数