首页 > 其他 > 详细

jvm面试题(纯手撸)

时间:2020-11-16 14:56:03      阅读:40      评论:0      收藏:0      [点我收藏+]

1.jvm内存模型:

线程独占:java虚拟机栈、本地方法栈、程序计数器

线程共享:堆、方法区(jdk1.7永久代和1.8的元空间都是方法区的实现)

2.java虚拟机栈

java虚拟机栈是线程私有的,每个方法执行的时候,java虚拟机栈都会同步创建一个栈帧,栈帧中存储操作数栈、局部变量表、动态链接、方法出口等信息,

每个方法被调用直至执行完毕的过程对应一个栈帧在虚拟机栈中的入栈和出栈过程

3.本地方法栈

与java虚拟机栈类似,用来保存执行方法的信息,不同的是,执行java方法使用的是java虚拟机栈,执行native方法使用的是本地方法栈

4.程序计数器

保存当前线程执行的字节码的位置,每个线程都会有一个程序计数器,只为执行java方法服务,执行native方法,程序计数器为空

5.堆

java内存管理最大的一个区域,目的是存放对象,数据被多个线程共享,当堆中内存不足时会产生OOM异常,根据对象的存活周期不同,jvm把对象进行分代管理,由垃圾回收器自动回收

6.方法区

又称非堆区,多个线程共享,主要用来存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码缓存等数据,jdk1.7的永久代和jdk1.8的元空间都是方法区的一种实现

7.jvm内存可见性

技术分享图片

 

 

 JMM定义了程序中各个共享变量的访问规则,线程对于变量的操作只能在自己的工作内存中进行,而不能直接对主内存操作,由于指令重排序,读写的顺序会被打乱,因此JMM需要提供原子性,可见性,有序性保证

技术分享图片

 

 

 8.类加载与卸载

技术分享图片

 

 

 其中验证,准备,解析合称链接

加载是整个"类加载 class loading"过程中的一个阶段,不要混淆。加载阶段,java虚拟机需要做3件事:

1.通过一个类的全限定名获取定义此类的二进制字节流

2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

3.在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据访问的入口

验证确保class文件符合当前虚拟机的要求,不会危害到虚拟机自身安全

准备进行内存分配,为static修饰的类变量分配内存,并设置初始值(0或null)。不包含final修饰的静态变量,因为final变量在编译时分配,这时候分配的初始值为零值,假设一个变量定义为:public static int value = 123;则设置变量的初始值应该为0, 而不是123。 把value赋值为123的putstatic指令是在程序被编译后,存放于类构造器<clinit>()方法之中,所以把value赋值为123的动作将在初始化阶段才会执行。如果字段属性表中存在ConstantValue属性,那么在准备阶段会将value赋值为ConstantValue属性所指定的值 。例如:public static final int value = 123; 那么在准备阶段,则会将value赋值为123;

解析将常量池中的符号引用替换为直接引用的过程,直接引用为直接指向目标的指针或相对偏移量

初始化主要完成静态块执行以及静态变量的赋值,先初始化父类,再初始化当前类,只有对类主动使用时才会初始化。触发条件包括:创建类的示例时、访问类的静态变量或静态方法时,使用class.forName反射类的时候或者某个子类初始化的时候

java自带的加载器加载的类,在虚拟机的生命周期中是不会被卸载的,只有用户自定义的加载器加载的类才可以被卸载

1.加载机制-双亲委派模式

技术分享图片

各个加载器加载范围:

  Bootstrap classloader:负责加载%java_HOME%\lib目录下的类或者被-Xbootclasspath参数所指定的路径中存放的。而且是java虚拟机能够识别的(按照文件识别,如rt.jar、tools.jar,名字不符合的类库即使放在lib目录也不会被加载)类库加载到虚拟机的内存中。

  Ext classloader:负责加载<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量所指定的路径中的所有的类库

  App classloader: 负责加载用户类路径(classpath)上的所有类库

  优点:

  1.避免类的重复加载

  2.避免java的核心API被篡改

 如何打破双亲委派机制?

重写父类的loadclass方法即可。(如果不想打破,只需要重写findclass方法)

 10.常见的垃圾回收算法:

  引用计数算法:通过对象被引用的次数确定对象是否被使用,缺点是无法解决循环引用的问题

  标记清除算法:

  缺点1:执行效率不稳定,如果java堆中包含大量对象,而且大部分是需要被回收的,这时必须要进行大量的标记-清除的动作,导致标记-清除两个过程的执行效率随对象数量增长而降低。

  缺点2:标记清除会产生大概不连续的内存碎片,导致当以后在程序运行过程中需要分配较大对象时无法找到足够的连续空间而不得不提前触发另一次的垃圾收集动作

  标记-复制算法:

    优点:解决内存碎片问题

    缺点1:如果内存中多数对象是存活的,会产生大量的内存复制开销

  标记整理算法:与标记清除算法相同,不过在清除后会进行内存整理

  分代收集算法: 当前商业虚拟机的垃圾收集都是采用垃圾收集算法,根据对象存活周期不同,将内存分为几块,一版分为新生代和老年代,新生代有大批量对象死去、存活的对象少,采用复制算法,只需要占用部分存活对象的内存开销就可以了。

  老年代中大部分对象都是存活的,只有少量对象会死去,采用标记-清除、标记-整理算法

 参考:https://www.jianshu.com/p/1e4011617650

jvm面试题(纯手撸)

原文:https://www.cnblogs.com/kiwi-deng/p/13965306.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!