JVM常见问题

发布于:2024-03-28 ⋅ 阅读:(71) ⋅ 点赞:(0)

一,java中有哪些类加载器?

自带三个类加载器,BootstrapClassLoader载%JAVA_HOME/%lib下的jar包和class文件,ExtClassLoader,AppClassLoader加载%JAVA_HOME%/lib/ext文件夹下的jar包和class文件,

AppClassLoader负责加载classpath下的类文件。Bootstrap是Ext的父类加载器,Ext是App的父类加载器。

二,说说类加载双亲委派模型。

答出来三个自带的类加载器以及三者父类的关系。

JVM在加载一个类时,会调用AppClassLoader的loadClass方法来加载这个类,不过在这个方法中,会先使用ExtClassLoader的loadClass方法来加载类,同样ExtClassLoader的loadClass方法中会先使用BootstrapClassLoader来加载类,如果BootstrapClassLoader加载到了就直接成功,如果BootstrapClassLoader没有加载到,那么ExtClassLoader就会自己尝试加载该类,如果没有加载到,那么则会由AppClassLoader来加载这个类。

所以,双亲委派指得是,JVM在加载类时,会委派给Ext和Bootstrap进行加载,如果没加载到才由自己进行加载。

三,JVM中哪些是线程共享区

堆区和方法区是所有线程共享的,栈、本地方法栈、程序计数器是每个线程独有的

四,你们项目如何排查JVM问题

(命令很重要)

对于还在正常运行的系统:

1.可以使用jmap来查看JVM中各个区域的使用情况
2.可以通过jstack来查看线程的运行情况,比如哪些线程阻塞、是否出现了死锁
3.可以通过jstat命令来查看垃圾回收的情况,特别是fullgc,如果发现fullgc比较频繁,那么就得进行调优了
4.通过各个命令的结果,或者jvisualvm等工具来进行分析
首先,初步猜测频繁发送fullgc的原因,如果频繁发生fullgc但是又一直没有出现内存溢出,那么表示fullgc实际上是回收了很多对象了,所以这些对象最好能在younggc过程中就直接回收掉,避免这些对象进入到老年代,对于这种情况,就要考虑这些存活时间不长的对象是不是比较大,导致年轻代放不下,直接进入到了老年代,尝试加大年轻代的大小,如果改完之后,fullgc减少,则证明修改有效
同时,还可以找到占用CPU最多的线程,定位到具体的方法,优化这个方法的执行,看是否能避免某些对象的创建,从而节省内存
对于已经发生了OOM的系统:

一般生产系统中都会设置当系统发生了OOM时,生成当时的dump文件(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/base)
我们可以利用jsisualvm等工具来分析dump文件
根据dump文件找到异常的实例对象,和异常的线程(占用CPU高),定位到具体的代码
然后再进行详细的分析和调试

总之,调优不是一蹴而就的,需要分析、推理、实践、总结、再分析,最终定位到具体的问题。

五,JVM出现OOM异常会导致进程挂掉吗?

当一个线程在执行代码的过程中,大概率需要创建对象,而创建对象就需要分配内存,如果JVM可用内存不够时会进行垃圾回收,如果垃圾回收完了之后内存还是不够就会抛出OutOfMemoryError,如果没有捕获OutOfMemoryError,那么就像抛出一个普通异常一样会导致线程停掉,如果捕获了OutOfMemoryError,那么线程可能就不会停掉,其实不管当前线程会不会停掉,跟进程会不会挂掉没有直接关系,也就是出现了OutOfMemoryError最多只会导致线程停掉,如果一个进程里面的所有非守护线程都停掉了,那么进程才会停掉,或者进程占了操作系统的过多内存,那么这个进程可能会被操作系统关闭掉。

六,一个对象从加载到JVM,再到被GC清除,都经历了什么过程?

1.首先把字节码文件内容加载到方法区
2.然后再根据类信息在堆区创建对象
3.对象首先会分配在堆区中年轻代的Eden区,经过一次Minor GC后,对象如果存活,就会进入Suvivor区。在后续的每次Minor GC中,如果对象一直存活,就会在Suvivor区来回拷贝,每移动一次,年龄加1
4.当年龄超过15后,对象依然存活,对象就会进入老年代
5.如果经过Full GC,被标记为垃圾对象,那么就会被GC线程清理掉

七,怎么确定一个对象到底是不是垃圾?

1. 引用计数算法: 这种方式是给堆内存当中的每个对象记录一个引用个数。引用个数为0的就认为是垃圾。这是早期JDK中使用的方式。引用计数无法解决循环引用的问题。
2. 可达性算法: 这种方式是在内存中,从根对象向下一直找引用,找到的对象就不是垃圾,没找到的对象就是垃圾。

八,JVM有哪些垃圾回收算法?

1. 标记清除算法:
  a. 标记阶段:把垃圾内存标记出来
  b. 清除阶段:直接将垃圾内存回收。
  c. 这种算法是比较简单的,但是有个很严重的问题,就是会产生大量的内存碎片。
2. 复制算法:为了解决标记清除算法的内存碎片问题,就产生了复制算法。复制算法将内存分为大小相等的两半,每次只使用其中一半。垃圾回收时,将当前这一块的存活对象全部拷贝到另一半,然后当前这一半内存就可以直接清除。这种算法没有内存碎片,但是他的问题就在于浪费空间。而且,他的效率跟存活对象的个数有关。
3. 标记压缩算法:为了解决复制算法的缺陷,就提出了标记压缩算法。这种算法在标记阶段跟标记清除算法是一样的,但是在完成标记之后,不是直接清理垃圾内存,而是将存活对象往一端移动,然后将边界以外的所有内存直接清除。

九,什么是STW?

STW: Stop-The-World,是在垃圾回收算法执行过程当中,需要将JVM内存冻结的一种状态。在STW状态下,JAVA的所有线程都是停止执行的-GC线程除外,native方法可以执行,但是,不能与JVM交互。GC各种算法优化的重点,就是减少STW,同时这也是JVM调优的重点。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到