自学内容网 自学内容网

java面试题(jvm)

目录

jvm组成

1.jvm由哪些部分组成?

2.什么是程序计数器

3.什么是堆?

4.什么虚拟机栈?

5.栈和堆的区别?

6.什么是方法区?

7.什么是直接内存?

类加载器

1.什么是类加载器?

2.有哪些类加载器?

3.双亲委派模型

4.类加载器的执行过程

垃圾回收

1.对象什么时候可以被垃圾器回收

2.有哪些垃圾回收算法

3.分代回收

4.jvm有哪些垃圾回收器

5.G1垃圾回收器

6.强引用、软引用、弱引用、虚引用

jvm实践

1.jvm调优可以在哪设置?

2.jvm调优参数

3.jvm调优工具

4.java内存泄漏排查

5.cpu飙高排查方案与思路


jvm组成
1.jvm由哪些部分组成?

jvm主要分为下面几个部分:

        类加载器:将java代码转换成字节码

        运行时数据区:把字节码加载到内存

        执行引擎:把字节码翻译成底层系统指令

        本地库接口:执行引擎调用参与字节码的翻译

其中最主要的就是运行时数据区,它由5部分组成,分别是堆、栈、本地方法栈、方法区、程序计数器

2.什么是程序计数器

程序计数器:线程私有的,每个线程一份,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。

3.什么是堆?

是一个线程共享的区域,主要用来保存对象实例,数组等,内存不够则抛出异常。

由年轻代和老年代组成:

        年轻代:划分为三部分,Eden区和两个Survivor区

        老年代:主要保存生命周期长的对象

其中jdk1.7和jdk1.8的区别:

        1.7中有一个永久代,存储类信息、静态变量、常量

        1.8中移除了永久代,把数据存储到了本地内存的元空间中,防止内存溢出

4.什么虚拟机栈?

虚拟机栈:每个线程运行时所需要的内存,先进后出;每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存;但是每个线程只能有一个活动栈帧,对应着正在执行的按个方法。

垃圾回收是否涉及栈内存?

不涉及;垃圾回收主要是指堆内存,当栈帧弹帧后内存就会释放。

栈内存分配的越多越好吗?

不一定。默认为1024k,栈帧过大会导致线程数变少,如:机器内存为512m,目前活动的线程数就是512个,如果改为2048k,那么能活动的栈帧就会减半。

方法内的局部变量是否线程安全?

1.安全,如果方法内局部变量没有逃离作用范围(如:在方法内创建对象,并没有返回值)

2.不安全,引用了对象,并逃离了方法的作用范围(如:外部传入对象,或有返回值)

什么情况下会导致栈内存溢出?

1.栈帧过多,如方法内自调用

2.栈帧过大

5.栈和堆的区别?

栈内存存储的是局部变量而堆内存存储的是实体;

堆会GC垃圾回收,而栈不会;

栈内存线程是私有的,堆内存线程是共有的;

异常错误不同;栈内存抛出栈空间不足异常,堆内存抛出堆空间不足异常;

6.什么是方法区?

方法区:是各个线程共享的内存区域。主要存储类的信息、运行时常量池;虚拟机启动的时候创建,关闭虚拟机时释放,如果方法区域中的内存无法满足分配要求,则会抛出空间不足异常。

运行时常量池:可以看做一张表,虚拟机指令根据这张表找到要执行的类名、方法名、参数类型、字面量等信息;当类被加载时,它的常量池信息就会放入运行时常量池,并把地址符号换成真实地址。

7.什么是直接内存?

直接内存并不属于jvm中的内存结构,不由jvm进行管理,是机器的系统内存。常见于NIO操作时,用于数据缓冲区,分配回收成本较高,但读写性能高,不受jvm内存回收管理。

类加载器
1.什么是类加载器?

jvm只会运行二进制文件,类加载器的作用就是将字节码文件加载到jvm中,从而让java程序能够启动起来。

2.有哪些类加载器?

启动类加载器:加载jre/lib下的类

扩展类加载器:加载jre/lib/ext下的类

应用类加载器:加载classPath的类,默认

自定义类加载器: 自定义继承,实现加载规则

3.双亲委派模型

加载某一个类,先委托上一级的加载器进行加载,如果上一级加载器也有上一级,则继续向上委托,如果委托到最上级没被加载,子加载器也尝试加载该类。

jvm为什么采用?

通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载则无需重复鸡杂,保证唯一性。为了安全,保证类库API不会被修改。

4.类加载器的执行过程

加载:查找和导入class文件

验证:保证加载类的准确性

准备:为类变量分配内存和设置初始值

解析:把类中的符号引用转化为直接引用

初始化:对类的静态变量、静态代码执行初始化

使用:执行程序代码

卸载:执行完毕后,销毁创建的class对象

垃圾回收
1.对象什么时候可以被垃圾器回收

如果一个或多个对象没有任何的引用指向它了,那么这个对象就是垃圾,如果定位了垃圾,则有可能会被回收。

引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;

可达性分析算法:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

2.有哪些垃圾回收算法

1.标记清除算法:分为两个阶段,标记和清除,效率高,有磁盘碎片,内存不连续

2.标记整理算法:和清除算法一样,将存活对象都向内存另一端移动,然后清理边界以外的垃圾,无碎片。但对象需要移动,效率低

3.复制算法:将原有空间一分为二,每次使用一块,将正在使用的对象复制到另一个内存空间中,然后将内存空间清空,交换两个内存的角色,完成垃圾回收;无碎片,内存使用率低

3.分代回收

堆的区域划分:

1.堆被分为了两份:新生代和老年代(1:2)

2.对于新生代,其内部又分为了三个区域,Eden区,幸存者区(分为from和to),(8:1:1)

对象回收分代回收策略:

1.新创建的对象,都会先分配到eden区
2.当伊甸园内存不足,标记伊甸园与from(现阶段没有)的存活对象
3.将存活对象采用复制算法复制到to中,复制完毕后,伊甸园和 from 内存都得到释放4.经过一段时间后伊甸园的内存又出现不足,标记eden区域to区存活的对象,将其复制到from区5.当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会提前晋升)

4.jvm有哪些垃圾回收器

串行垃圾收集器:Serial(作用在新生代)、Serial Old(作用在老年代)

并行垃圾收集器:Parallel(作用在新生代)、Parallel Old(作用在老年代)

CMS:作用在老年代

G1:作用在新生代和老年代

5.G1垃圾回收器

应用于新生代和老年代,在JDK9之后默认使用G1;

划分成多个区域,每个区域都可以充当 eden,survivor,old,humongous其中 humongous 专为大对象准备;

采用复制算法;
响应时间与吞吐量兼顾;
分成三个阶段:新生代回收(stw)、并发标记(重新标记stw)、混合收集;

如果并发失败(即回收速度赶不上创建新对象速度),会触发FuGC;

6.强引用、软引用、弱引用、虚引用

强引用:只要所有 GC Roots 能找到,就不会被回收

如·:User u = new User();

软引用:需要配合SoftReference使用,当垃圾多次回收,内存依然不够的时候会回收软引用对象

如·:User u = new User();

        SoftReference s = new SoftReference(u);

弱引用:需要配合WeakReference使用,只要进行了垃圾回收,就会把弱引用对象回收

如·:User u = new User();

        WeakReferences = new WeakReference(u);

虚引用:必须配合引用队列使用,被引用对象回收时,会将虚引用入队由 Reference Handler 线程调用虚引用相关方法释放直接内存

如·:User u = new User();

        SoftReference s = new SoftReference();

        WeakReferences = new WeakReference(u,s);

jvm实践
1.jvm调优可以在哪设置?

war包部署:在/bin/catalina.sh文件中修改 JAVA_OPTS=" -Xms512m -Xmx1024m";

jar包部署:在启动参数时设置:java  -Xms512m -Xmx1024m -jar xxx.jar;

2.jvm调优参数

1.设置堆空间大小:通常把堆的最大大小和初始大小设置一致, -Xms、-Xmx设置

2.设置虚拟机栈:每个线程默认开启1M的内存,通常256k就够了,-Xss设置

3.设置垃圾回收器:通过增大吞吐量提高系统性能,-XX:+UseG1GC设置

4.年轻代晋升老年代的阈值:默认15,取值范围为0-15

5.年轻代中Eden区和两个Survivor区的比例大小:通过-XXSurvivorRatio=8来设置,默认:8:1:1

3.jvm调优工具

命令工具:

        jps:进程状态信息
        jstack:査看java进程内线程的堆栈信息
        jmap:查看堆转信息
        jhat:堆转储快照分析工具。
        jstat:JVM统计监测工具

可视化工具:

        jconsole:用于对ivm的内存,线程,类 的监控

        VisualVM:能够监控线程,内存情况

4.java内存泄漏排查

内存泄露一般是指堆内存,通常是指一些大对象不被回收的情况;

步骤:

        1.通过设置jvm参数获取堆内存快照dump

        2.通过工具VisualVM去分析dump文件,VisualVM可以加载离线的dump文件

        3.通过查看堆信息的情况,可以分析定位到内存溢出的代码行数

        4.找到对应代码,通过阅读上下文,进行修复

5.cpu飙高排查方案与思路

1.使用top命令,查看cpu的占用情况,可以查看到哪一个进程占用cpu较高;

2.使用ps命令,查看进程中线程信息;(PS H -eo pid,tid,%cpu l grep 进程ID)

3.通过jstack命令,查看进程中哪些线程出现问题,最终定位问题。(jstack 进程ID)


原文地址:https://blog.csdn.net/qq_35056891/article/details/143485278

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!