java面试题:jvm

jvm内存区域

Q:jvm内存怎么划分的?
答:
方法区(线程共享):各个线程共享的一个区域,用于存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却又一个别名叫做 Non-Heap(非堆),目的应该是与 Java 堆区分开来。
运行时常量池:是方法区的一部分,用于存放编译器生成的各种字面量和符号引用。
堆内存(线程共享):所有线程共享的一块区域,垃圾收集器管理的主要区域。主要存储对象、数组。
Java 堆中还可以细分为:新生代和老年代;再细致一点的有 Eden 空间、From Survivor 空间、To Survivor 空间等,默认情况下新生代按照8:1:1的比例来分配。
程序计数器: Java 线程私有,它可以看做是当前线程所执行的字节码的行号指示器。
虚拟机栈(栈内存):Java线程私有,虚拟机展描述的是Java方法执行的内存模型:每个方法在执行的时候,都会创建一个栈帧用于存储局部变量、操作数、动态链接、方法出口等信息;每个方法调用都意味着一个栈帧在虚拟机栈中入栈到出栈的过程;
本地方法栈 :和Java虚拟机栈的作用类似,区别是该区域为 jvm提供使用 native 方法的服务。

垃圾收集算法

Q:垃圾收集算法有哪些?
标记-清除算法、复制算法、标记-整理算法、分代收集算法
Q:垃圾回收器有哪些?
Java有四种类型的垃圾回收器:
串行垃圾回收器(Serial Garbage Collector)
并行垃圾回收器(Parallel Garbage Collector)
并发标记扫描垃圾回收器(CMS Garbage Collector)
G1垃圾回收器(G1 Garbage Collector)
Q:垃圾收集器有哪些?
垃圾收集器:Serial收集器、ParNew收集器、Parallel Scavenge收集器、Serial Old收集器、Parallel Old收集器、CMS收集器、G1收集器
Jdk11推出了ZGC,号称可以达到10ms 以下的 GC 停顿,承诺在数TB的堆上具有非常低的暂停时间。

内存分配与回收策略

Q:内存分配有哪些规则?
对象分配规则?
答:
有新生代和老年代。新生代又分为 Eden区、ServivorFrom、ServivorTo三个区。
(1)对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC。
(2)大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。
(3)长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,知道达到阀值对象进入老年区。
(4)动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。
(5)空间分配担保。每次进行Minor GC时,jvm会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Minor GC,如果false则进行Full GC。

Q:MinorGC、MajorGC、FullGC的区别是什么?
Minor GC:简单理解就是发生在年轻代的GC。
Minor GC的触发条件为:
当产生一个新对象,新对象优先在Eden区分配。
如果Eden区放不下这个对象,虚拟机会使用复制算法发生一次Minor GC,清除掉无用对象,同时将存活对象移动到Survivor的其中一个区(fromspace区或者tospace区)。
如果新生对象在Eden区无法分配空间时,此时发生Minor GC。
发生MinorGC,对象会从Eden区进入Survivor区,如果Survivor区放不下从Eden区过来的对象时,此时会使用分配担保机制将对象直接移动到年老代。

Major GC的触发条件:Major GC又称为Full GC。当年老代空间不够用的时候,虚拟机会使用“标记—清除”或者“标记—整理”算法清理出连续的内存空间,分配对象使用。出现Major GC通常会出现至少一次Minor GC?
Q:年轻代,老年代,分别采用哪些垃圾回收算法?
年轻代的垃圾回收是Minor GC,采用的垃圾回收算法是复制算法。
老年代的垃圾回收是Full GC,采用的垃圾回收算法是标记--清除算法

类的加载机制

Q:java 中都有哪些引用类型?
Q:ClassLoader类加载是发生在哪块内存区域?
答:将Java类的.class文件中的二进制数据读入到内存中,放置在运行时数据区的方法区内。(存疑)
Q:讲一下类加载的过程。
虚拟机类加载机制的生命周期:加载,验证,准备,解析,初始化,使用,卸载。
其中,验证,准备,解析这三个过程又称为“连接”。
Q:类的加载器ClassLoader有哪些?
JVM提供了3种类加载器: BootstrapClassLoader、 ExtClassLoader、 AppClassLoader分别加载Java核心类库、扩展类库以及应用的类路径( CLASSPATH)下的类库。
Q:类的加载机制是怎样的?
双亲委派机制。
当一个类加载器收到类加载任务时,会先交给自己的父加载器去完成,因此最终加载任务都会传递到最顶层的BootstrapClassLoader,只有当父加载器无法完成加载任务时,才会尝试自己来加载。
采用双亲委派模型的一个好处是保证使用不同类加载器最终得到的都是同一个对象,这样就可以保证Java 核心库的类型安全,比如,加载位于rt.jar包中的 java.lang.Object类,不管是哪个加载器加载这个类,最终都是委托给顶层的BootstrapClassLoader来加载的,这样就可以保证任何的类加载器最终得到的都是同样一个Object对象。

jvm调优

Q:jvm有哪些参数?
-XmsSize(最小堆内存)
-XmxSize(最大堆内存)
-XmnSize(分配给年轻代)
-XX:+PrintGCDetails 输出详细GC日志
-XX:SurvivorRatio=ratio Eden区和survivor区的比例
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:-UseTLAB 是否使用本地线程分配缓冲
-XX:+HeapDumpOnOutOfMemoryError(在出现异常的情况下 将内存快照dump出来)
-XssSize 栈大小
-XX:MaxPermSize 方法区的最大值(JDK<=1.7 1.8将方法区移去,增加了metaspaces)
-XX:PermSize 方法区的大小

java内存模型

Q:java的内存模型是怎样的?
Java 虚拟机规范中试图定义一种 Java 内存模型(Java Memory Model, JMM)来屏蔽掉各层硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。
Java 内存模型规定了所有的变量都存储在主内存(Main Memory)中。每条线程还有自己的工作内存(Working Memory),线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在主内存中进行,而不能直接读写主内存中的变量。不同的线程之间也无法直接访问对方工作内存中的变量,线程间的变量值的传递均需要通过主内存来完成

待补充.

参考资料:
《深入理解java虚拟机》
《深入理解java虚拟机》学习笔记

原文地址:https://www.cnblogs.com/expiator/p/10251645.html