java面试题目之JVM(YW制作仅供参考)

 

1.JVM工作原理

 

 

 

 

 

2.JVM组成部分及其作用。

java虚拟机分为两个子系统和两个组件。

两个子系统分别是类加载器和执行引擎,类加载器负责加载字节码(.class)文件到JVM的内存中,执行引擎负责执行classes下面的指令,还可以修改程序计数器的值。

两个组件分别是运行时数据区和本地方法接口。

运行时数据区也就是JVM的内存,本地方法接口就是和其他语言交互的接口。

3.java应用程序运行的步骤。

首先通过IDE集成环境编写java代码,其次通过编译器将java文件编译成字节码文件,然后通过类加载器将.class文件加载到JVM内存中。(运行字节码是由解析器完成)。

4.类加载的过程。

类加载分三步。加载-连接-初始化

①加载。类加载器将.class文件加载到JVM内存中。

②连接。校验:判断.class文件的安全性和正确性。

    准备:为静态变量赋值,这个值是默认值。(为静态变量分配内存空间),如果有final修饰的变量,则赋原值。

    解析:把符号引用转换为直接引用。

③初始化。执行静态代码块,为静态变量赋值,这个值是原值。

5.JVM的类加载器。

作用:负责加载字节码文件到JVM'的内存中。

从父类加载器到子类加载器一共分为4种。分别是启动类加载器(加载核心类),扩展类加载器(加载扩展的jar),应用程序类加载器(加载classpath下面指定的内容),自定义类加载器(加载自定义的jar)。

6.双亲委派机制

为了能够让类加载器按需加载,避免重复加载,所以引入了双亲委派机制。

这个机制说白了就是一个类加载器的层次模型,一个类加载器收到了一个加载类的请求,首先他不会自己尝试去加载这个类,而是由父类加载器去加载,所以每个加载的请求都会传送到根类加载器,只有当父类反馈无法加载这个类之后,子类加载器才会尝试去加载。

使用双亲委派机制就是避免多份同样的字节码文件的加载,通过一层一层向上,看看哪一个类加载器曾经加载过这个字节码文件。

7.forname和classload的区别。

二者都是类加载的一种显示方式,forname得到的class是已经初始化的,而classload得到的class是没有进行连接的。

判断:写一个类,然后在这个类中写一段静态代码块,如果使用forname发现静态代码块被执行,使用classload发现静态代码没有被执行。

8.JVM内存模型

jvm内存模型也就是运行时数据区。

它分为方法区(元空间java8以后),java虚拟机栈,堆,程序计数器,本地方法栈。

程序计数器(线程独有):它是一块较小的内存空间,他表示字节码执行的行数,通过改变程序计数器的值来判断要执行哪一条指令,程序之间的跳转就是通过程序计数器实现的,他属于逻辑计数器。

java虚拟机栈(线程独有):是java方法执行的模型,每一次方法执行时都会创建一个栈帧,栈帧里面存放了本地变量表,操作数栈,动态链接,方法返回值。本地变量表存放本地变量,操作数栈错放临时变量值。

本地方法栈(线程独有):和java虚拟机栈类似,不过就是java虚拟机栈服务的对象是java方法,而本地方法栈为native方法服务。

方法区(线程共享)(元空间):存放一些编译器编译过后的一些代码等数据。

堆(线程共享):存放一些实例(对象),也是垃圾收集管理的区域。java堆分为年轻代和老年代。

9.JVM分代怎么工作的

jvm分为年轻代和老年代,年轻代又分为一个Eden区和两个survivor(from和to),默认比例8:1:1,。首先对象是放在Eden区和from区的,当发生GC,Eden区存活的对象就会被放到to区,然后from区的对象就会根据年龄判断去to区还是去老年代,默认年龄15。此时Eden和from为空,然后to区和from区交换。

10.java堆和栈的区别

从内存空间看:栈小于堆

从管理上看:栈自动释放,堆需要GC

从线程看:堆是线程共享的,栈是线程独有的

从分配上看:堆是动态分配,栈是静态和动态分配

从效率上看:栈大于堆

11.如何判断垃圾可以被回收

判断垃圾是否应该回收有两种方法:程序计数法,可达性分析法。

程序计数法:通过判断对象引用的次数来判断是否被回收,每个对象都会有一个引用计数器,被引用时应用技术器+1,引用完成时引用计数器-1,引用计数器为0时,就说明此对象可以视为垃圾。这种方式有一个弊端,就是假设父对象引用子对象,子对象反过来引用父对象,这样引用计数器的值永远不可能为0,会导致内存泄漏。

可达性分析法:通过判断对象的引用链来判断对象是否为垃圾。从GCroot开始寻找引用节点,然后继续寻找这个节点的引用节点,当所有引用节点寻找完毕,则剩下的节点就是没有被引用的,就可以视为垃圾。

12.什么可以被视为GC root。

java虚拟机栈中引用的对象(栈帧的本地变量表)

方法区中静态变量引用的对象

方法区中常量引用的对象

本地方法中native引用的对象

13.垃圾回收算法

标记-清除算法:在堆中从根节点进行扫描,对存活的对象进行标记,对堆从头到尾进行遍历,然后清除不可达的对象。这种算法会产生大量的垃圾碎片,不利于以后大对象的储存。

复制算法:刚开始把堆分为一个对象面和一个空闲面,首先在对象面进行对象分配,当对象面满了,就会将对象面存活的对象复制到空闲面,这样对象面就变成了空闲面,空闲面就变成了对象面。然后程序就在空闲面进行对象分配。

标记-整理算法:在堆中从根节点进行扫描,对存活的对象进行遍历,然后通过地址将存活的对象依次排序,将末节点地址以后全部清除。

分代收集算法:新生代(存活率低):复制算法

       老年代(存活率高):标记-清除算法和标记-整理算法

14.Minor GC 和 Full GC,触发Full GC的条件

Minor GC发生在年轻代,首先对象分配在伊甸园区,如果伊甸园区放不下了,也有可能直接放到survivor区。

Full GC发生在老年代。

条件:老年代空间不足:因为标记-清除算法会产生垃圾碎片,会导致老年代空间不足,就会触发Full GC

   永久代空间不足

   CMS时出现有对象进入老年代导致老年代空间不足

   调用System.gc()

15.垃圾收集器

年轻代:Serial垃圾收集器(单线程)  ParNew垃圾收集器(多线程)  Parallel Scavenge垃圾收集器(多线程可控制吞吐量)

老年代:Serial Old垃圾收集器(单线程)  Parallel Old垃圾收集器(多线程可控制吞吐量)  CMS垃圾收集器(标记-清除算法实现)

整堆回收器:G1

CMS:

 

16.JVM调优

工具:jconsole:对JVM线程  类等进行监控

   jvisualvm:JDK自带分析工具,分析:内存快照,程序死锁,监控内存变化,GC变化

参数:-Xms2g:初始化堆大小为2g

   -Xmx2g:堆最大为2g

   -xx:NewRatio=4:年轻代:老年代=4:1

   -xx:survivorRatio=8   Eden:survivor=8:2

.......

 

17.软引用和弱引用

软引用:一般维护一些可有可无的对象,内存足够的时候,软引用对象不会被回收,只有当内存不足的时候软引用对象才会被回收,如果回收之后内存依然不足,才会抛出内存溢出异常。

弱引用:更加无用,无论内存是否够用,弱引用对象都会被回收。

 

posted @ 2020-07-14 12:10  ITYW  阅读(190)  评论(0编辑  收藏  举报