宁波网站建设联系荣胜,深圳南山logo设计公司,网站运营方案书,工程建设标准网站目录
JVM的组成#xff1a;
1、JVM 概述(⭐⭐⭐⭐)
1.1 JVM是什么#xff1f;
1.2 JVM由哪些部分组成#xff0c;运行流程是什么#xff1f;
2、什么是程序计数器#xff1f;(⭐⭐⭐⭐)
3、介绍一下Java的堆(⭐⭐⭐⭐)
4、虚拟机栈(⭐⭐⭐⭐)
4.1 什么是虚拟机栈
1、JVM 概述(⭐⭐⭐⭐)
1.1 JVM是什么
1.2 JVM由哪些部分组成运行流程是什么
2、什么是程序计数器(⭐⭐⭐⭐)
3、介绍一下Java的堆(⭐⭐⭐⭐)
4、虚拟机栈(⭐⭐⭐⭐)
4.1 什么是虚拟机栈
4.2 垃圾回收是否涉及栈内存
4.3 栈帧内存分配越大越好吗
4.4 方法内的局部变量是否线程安全
4.5 什么情况下会导致栈内存溢出
4.6 堆栈的区别是什么
5、介绍一下方法区(⭐⭐⭐)
5.1 方法区概述
5.2 运行时常量池
6、直接内存(⭐⭐⭐)
类加载器
7、什么是类加载器类加载器有哪些?(⭐⭐⭐)
8、双亲委派模型(⭐⭐⭐⭐)
9、类装载的执行过程(⭐⭐⭐)
垃圾回收
10、对象什么时候可以被垃圾器回收 (⭐⭐⭐⭐)
11、JVM 垃圾回收算法(⭐⭐⭐⭐)
12、分代收集算法(⭐⭐⭐⭐)
MinorGC、 Mixed GC 、 FullGC的区别是什么
13、JVM 垃圾回收器(⭐⭐⭐⭐)
14、强引用、软引用、弱引用、虚引用的区别
jvm实践
15、JVM 调优的参数可以在哪里设置参数值⭐⭐
16、JVM 调优的参数都有哪些⭐⭐⭐
17、JVM 调优的工具⭐⭐
18、Java内存泄露的排查思路⭐⭐⭐⭐
19、CPU飙高排查方案与思路⭐⭐⭐⭐ JVM的组成
1、JVM 概述(⭐⭐⭐⭐)
1.1 JVM是什么 jvm(Java Virtual Machine)是Java程序的运行环境java二进制字节码的运行环境。
优点 一次编写到处运行。(jvm屏蔽了各种操作系统)自动内存管理垃圾回收机制。
1.2 JVM由哪些部分组成运行流程是什么 JVM 的主要组成部分 :
ClassLoader类加载器 Runtime Data Area运行时数据区内存分区 Execution Engine执行引擎 Native Method Library本地库接口 运行流程 类加载器把Java代码转换为字节码。运行时数据区把字节码加载到内存中而字节码文件只是JVM的一套指令集规范并不能直接交给底层系统去执行而是有执行引擎运行。执行引擎将字节码翻译为底层系统指令再交由CPU执行去执行此时需要调用其他语言的本地库接口来实现整个程序的功能。 2、什么是程序计数器(⭐⭐⭐⭐) 程序计数器是线程私有的用于记录正在执行的字节码指令的地址。 java虚拟机对于多线程任务是通过线程轮流切换并分配线程执行时间来完成的。如果当前被执行的这个线程所分配的执行时间用完了【挂起】处理器会切换到另外的一个线程上执行。当这个线程的执行时间用完了接着处理器就会又来执行被挂起的这个线程。 为了使线程切换后能恢复到正确的执行位置每条线程都需要有一个独立的程序计数器各线程之间计数器互不影响独立存储。 程序计数器是唯一一个不会出现 OutOfMemoryError 的内存区域它的生命周期随着线程的创建而创建随着线程的结束而死亡。 3、介绍一下Java的堆(⭐⭐⭐⭐) 堆是线程共享的区域主要用来保存对象实例数组等当堆中没有内存空间可分配给实例也无法再扩展时则抛出OutOfMemoryError异常。组成年轻代老年代 年轻代被划分为三部分Eden区和两个大小严格相同的Survivor区。老年代主要保存生命周期长的对象一般是一些老的对象。Jdk1.7和1.8的区别 1.7中有有一个永久代方法区存储的是类信息、静态变量、常量、编译后的代码。1.8移除了永久代把数据存储到了本地内存的元空间中防止内存溢出。 4、虚拟机栈(⭐⭐⭐⭐) 4.1 什么是虚拟机栈 每个线程运行时所需要的内存称为虚拟机栈。每个栈由多个栈帧frame组成对应着每次方法调用时所占用的内存。每个线程只能有一个活动栈帧对应着当前正在执行的那个方法。 4.2 垃圾回收是否涉及栈内存 不涉及垃圾回收主要指就是堆内存当栈帧弹栈以后内存就会释放。 4.3 栈帧内存分配越大越好吗 未必默认的栈内存通常为1024k 。栈内存不变下栈帧过大会导致线程数变少。 4.4 方法内的局部变量是否线程安全 如果方法内局部变量没有逃离方法的作用范围它是线程安全的。如果局部变量逃离了方法的作用范围(如出现在形参或返回值)需要考虑线程安全。 4.5 什么情况下会导致栈内存溢出 栈帧过多导致栈内存溢出如递归调用栈帧过大导致栈内存溢出。 4.6 堆栈的区别是什么 栈内存一般会用来存储局部变量和方法调用但堆内存是用来存储Java对象和数组的。堆有GC垃圾回收而栈没有。栈内存是线程私有的而堆内存是线程共享的。两者异常错误不同栈内存或者堆内存不足都会抛出异常 栈空间不足java.lang.StackOverFlowError。 堆空间不足java.lang.OutOfMemoryError。 5、介绍一下方法区(⭐⭐⭐) 5.1 方法区概述 方法区(Method Area)是各个线程共享的内存区域。主要存储类的信息、运行时常量池。虚拟机启动的时候创建关闭虚拟机时释放。如果方法区域中的内存无法满足分配请求则会抛出OutOfMemoryError: Metaspace。 永久代是 JDK 1.8 之前的方法区实现JDK 1.8 及以后方法区的实现变成了元空间。永久代在堆中而元空间在本地内存发生OOM的概率比永久代小。 5.2 运行时常量池 常量池可以看作是一张表虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息当类被加载它的常量池信息就会放入运行时常量池并把里面的符号地址变为真实地址。 6、直接内存(⭐⭐⭐) 直接内存不受 JVM 内存回收管理属于操作系统的内存常见于 NIO 操作时用于数据缓冲区NIO读写性能比IO高。两者区别见下图 传统阻塞IO 的数据传输要走两次缓存区而NIO只需走一次。 类加载器 7、什么是类加载器类加载器有哪些?(⭐⭐⭐) 类加载器ClassLoader 的主要作用就是将类的 字节码文件加载到JVM 中 从而让 Java 程序能够启动起来。 类加载器根据各自加载范围的不同划分为四种类加载器 启动类加载器(BootStrap ClassLoader) 该类并不继承 ClassLoader 类其是由 C 编写实现。用于加载 JAVA_HOME/jre/lib 目录下的类库。 扩展类加载器(ExtClassLoader) 该类是ClassLoader的子类主要加载JAVA_HOME/jre/lib/ext目录中的类库。 应用类加载器(AppClassLoader) 该类是ClassLoader的子类主要用于加载classPath下的类也就是加载开发者自己编写的Java类。 自定义类加载器 开发者自定义类继承ClassLoader实现自定义类加载规则。 8、双亲委派模型(⭐⭐⭐⭐) 类加载器的体系并不是“继承”体系而是委派体系类加载器首先会到自己的parent中查找类或者资源如果找不到才会到自己本地查找。类加载器的委托行为动机是为了避免相同的类被加载多次。 为什么采用双亲委派机制 唯一性通过双亲委派机制可以避免某一个类被重复加载保证唯一性。 安全性 保证类库 API 不会被修改。 9、类装载的执行过程(⭐⭐⭐) 类从加载到虚拟机中开始直到卸载为止它的整个生命周期包括了7 个阶段 加载:查找和导入class文件。验证:验证类是否符合JVM规范安全性检查。准备:为类变量分配内存并设置类变量初始值。解析:把类中的符号引用转换为直接引用。初始化:对类的静态变量静态代码块执行初始化操作。使用:JVM 开始从入口方法开始执行用户的程序代码。卸载:当用户程序代码执行完毕后JVM便开始销毁创建的Class对象。 垃圾回收 10、对象什么时候可以被垃圾器回收 (⭐⭐⭐⭐) 如果没有任何的引用指向该对象了那么这个对象现在就是垃圾如果定位了垃圾则有可能会被垃圾回收器回收。 定位垃圾的方式 引用计数法给对象中添加一个引用计数器每被引用一次计数器就1反之-1。引用数为0时代表该对象可被回收。缺点循环引用时会出现内存泄漏可达性分析算法通过一系列的称为 “GC Roots”肯定不能当做垃圾回收的对象 的对象作为起点从这些节点开始向下搜索节点所走过的路径称为引用链当一个对象到 GC Roots 没有任何引用链相连的话则证明此对象是不可用的需要被回收。 可以作为GC Root的对象 虚拟机栈(栈帧中的局部变量表)中引用的对象本地方法栈(Native 方法)中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象所有被同步锁持有的对象JNIJava Native Interface引用的对象 11、JVM 垃圾回收算法(⭐⭐⭐⭐) 标记清除算法先根据可达性分析算法得出的垃圾进行标记再直接对这些标记为可回收的内容进行垃圾回收。 缺点通过标记清除算法清理出来的内存碎片化较为严重。标记整理算法标记阶段和上述类似在清理阶段并不是简单的直接清理可回收对象而是将存活对象都向内存另一端移动然后清理边界以外的垃圾从而解决了碎片化的问题。 缺点对象需要移动效率较低。复制算法将原有的内存空间一分为二每次只用其中的一块,正在使用的对象复制到另一个内存空间中然后将该内存空间清空交换两个内存的角色完成垃圾的回收。无碎片、效率较高。 缺点内存使用率低。 12、分代收集算法(⭐⭐⭐⭐) 根据对象存活周期的不同将内存分为几块。一般将 Java 堆分为新生代和老年代这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。 在新生代中每次收集都会有大量对象死去所以可以选择”标记-复制“算法只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的而且没有额外的空间对它进行分配担保所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。 对象回收分代回收的过程 新创建的对象首先会分配到伊甸园。当伊甸园内存不足标记伊甸园和幸存区from中的存活对象。使用复制算法将存活对象复制到to中然后释放from和eden的内存。一段时间后eden内存又不足标记eden和to中存活的对象复制到from中。当幸存区对象熬过几次回收(15次)晋身至老年代中。(幸存区内存不足或大对象会提前晋身) MinorGC、 Mixed GC 、 FullGC的区别是什么 MinorGC是 发生在新生代的垃圾回收暂停时间短 STW 。 FullGC 新生代 老年代完整垃圾回收暂停时间长 STW 应尽力避免。 Mixed GC 新生代 老年代部分区域的垃圾回收 G1 收集器特有 。 STW Stop-The-World 暂停所有应用程序线程等待垃圾回收的完成 。 13、JVM 垃圾回收器(⭐⭐⭐⭐) 串行垃圾收集器垃圾回收时只有一个线程在工作并且java应用中的所有线程都要暂停 STW 等待垃圾回收的完成适用于单机模式的虚拟机。 Serial作用于新生代采用复制算法。 Serial Old 作用于老年代采用标记 - 整理算法。 并行垃圾收集器 JDK8 默认使用此垃圾回收器 ParNew收集器是Serial收集器的多线程并行版本除了同时使用多条线程进行垃圾收集之外其余的行为与Serial收集器完全一致。除serial之外唯一能和CMS配合的Parallel Scavenge收集器新生代收集器基于标记-复制算法实现和ParNew非常相似区别在于该收集器更加关注吞吐量高效利用CPU。Parallel Old收集器是Parallel Scavenge收集器的老年代版本支持多线程并发收集基于标记-整理算法实现。CMS收集器以获取最短回收停顿时间为目标的收集器给用户带来良好的交互体验。 基于标记-清除算法实现整个过程分四个步骤初始标记和重新标记耗时较短需要STW暂停其他线程而整个过程中耗时最长的并发标记和并发清除阶段中垃圾收集器线程可以与用户线程并行工作。 初始标记标记GCRoots能直接关联到的对象速度很快。并发标记标记GC Roots的间接关联对象这个过程耗时较长但不需要停顿用户线程可以与垃圾收集线程一起并发运行。重新标记修正并发标记期间因用户程序继续运作而导致标记产生变动。并发清除清理删除掉标记阶段判断的已经死亡的对象由于不需要移动存活对象所以这个阶段也是可以与用户线程同时并发的。G1收集器 应用于新生代和老年代JDK9之后默认使用的收集器。 将java堆划分成多个区域每个区域都可以充当 edensurvivorold humongous 其中 humongous 专为大对象准备。 采用标记复制算法兼顾响应时间和吞吐量。 分为四个阶段 初始标记标记一下GC Roots能直接关联到的对象这个阶段需要停顿线程但耗时很短。并发标记从GC Root开始对堆中对象进行可达性分析递归扫描整个堆里的对象图找出要回收的对象这阶段耗时较长但可与用户程序并发执行。最终标记需要对用户线程做一个短暂的暂停解决上一阶段的漏标问题。筛选回收对各个Region的回收价值和成本进行排序根据用户所期望的停顿时间来制定回收计划可以自由选择任意多个Region构成回收集然后把这些Region中的存活对象复制到空的Region中再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动是必须暂停用户线程由多条收集器线程并行完成的。 停顿时间越短就越适合需要与用户交互或需要保证服务响应质量的程序良好的响应速度能提升用户体验而高吞吐量则可以最高效率地利用处理器资源尽快完成程序的运算任务主要适合在后台运算而不需要太多交互的分析任务。 14、强引用、软引用、弱引用、虚引用的区别 强引用最传统的“引用”的定义只要强引用关系还存在垃圾收集器就永远不会回收掉被引用的对象。软引用如果内存空间足够垃圾回收器就不会回收它如果内存空间不足了就会回收这些对象的内存。弱引用强度比软引用更弱当垃圾回收器开始工作时无论内存空间是否充足都会对弱引用的对象进行回收。虚引用虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用那么它就和没有任何引用一样在任何时候都可能被垃圾回收。主要用来跟踪对象被垃圾回收器回收的活动。 jvm实践 15、JVM 调优的参数可以在哪里设置参数值⭐⭐ war包部署在tomcat中设置 修改TOMCAT_HOME/bin/catalina.sh文件jar包部署在启动参数设置 java -Xms512m -Xmx1024m -jar xxxx.jar 16、JVM 调优的参数都有哪些⭐⭐⭐ 设置堆空间大小设置堆的初始大小和最大大小为了防止垃圾收集器在初始大小、最大大小之间收缩堆而产生额外的时间通常把最大、初始大小设置为相同的值。 -Xms设置堆的初始化大小-Xmx设置堆的最大大小虚拟机栈的大小每个线程默认会开启1M的内存用于存放栈帧、调用参数、局部变量等但一般256K就够用。 -Xss 对每个线程stack大小的调整,-Xss128k年轻代中Eden区和两个Survivor区的大小比例 -XXSurvivorRatio8表示年轻代中的分配比率survivor:eden 2:8年轻代晋升老年代阈值默认为15。 -XX:MaxTenuringThresholdthreshold设置垃圾回收收集器 -XX:UseParallelGC-XX:UseG1GC 17、JVM 调优的工具⭐⭐ 命令工具 jps输出JVM中运行的进程状态信息。jstack查看java进程内线程的堆栈信息。jmap用于生成堆转存快照。jhat用于分析jmap生成的堆转存快照。jstat是JVM统计监测工具。可以用来显示垃圾回收信息、类加载信息、新生代统计信 息等。 可视化工具 jconsole 对 jvm 的内存线程类进行监控是一个基于 jmx 的 GUI 性能监控工具。 打开方式java 安装目录 bin 目录下 直接启动 jconsole.exe 就行。 VisualVM故障处理工具能够监控线程内存情况查看方法的CPU时间和内存中的对象已被GC的对象反向查看分配的堆栈。 打开方式java 安装目录 bin目录下 直接启动 jvisualvm.exe就行。 18、Java内存泄露的排查思路⭐⭐⭐⭐ 内存泄漏通常是指堆内存通常是指一些大对象不被回收的情况。 1、通过jmap或设置jvm参数获取堆内存快照dump 2、通过工具 VisualVM去分析dump文件VisualVM可以加载离线的dump文件 3、通过查看堆信息的情况可以大概定位内存溢出是哪行代码出了问题 4、找到对应的代码通过阅读上下文的情况进行修复即可 19、CPU飙高排查方案与思路⭐⭐⭐⭐ 1.使用top命令查看占用cpu的情况查看是哪一个进程占用cpu较高。2.使用ps命令查看进程中的线程信息。3.使用jstack命令查看进程中线程的信息并定位到出问题的具体线程最终定位问题。