67 Star 534 Fork 87

鹏磊 / DevBooks

Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Please pay attention to the specific project description and its upstream code dependency when using it.
Clone or Download
Jvm最新2021年面试题,高级面试题及附答案解析.md 16.27 KB
Copy Edit Web IDE Raw Blame History

Jvm最新2021年面试题,高级面试题及附答案解析

全部答案,更新日期:12月29日,直接下载吧!

下载链接:高清172份,累计 7701 页大厂面试题 PDF

1、类加载的过程是什么?

加载

该阶段虚拟机需要完成三件事:① 通过一个类的全限定类名获取定义类的二进制字节流。② 将字节流所代表的静态存储结构转化为方法区的运行时数据区。③ 在内存中生成对应该类的 Class 实例,作为方法区这个类的数据访问入口。

验证

确保 Class 文件的字节流符合约束。如果虚拟机不检查输入的字节流,可能因为载入有错误或恶意企图的字节流而导致系统受攻击。验证主要包含四个阶段:文件格式验证、元数据验证、字节码验证、符号引用验证。

验证重要但非必需,因为只有通过与否的区别,通过后对程序运行期没有任何影响。如果代码已被反复使用和验证过,在生产环境就可以考虑关闭大部分验证缩短类加载时间。

准备

为类静态变量分配内存并设置零值,该阶段进行的内存分配仅包括类变量,不包括实例变量。如果变量被 final 修饰,编译时 Javac 会为变量生成 ConstantValue 属性,准备阶段虚拟机会将变量值设为代码值。

解析

将常量池内的符号引用替换为直接引用。

符号引用以一组符号描述引用目标,可以是任何形式的字面量,只要使用时能无歧义地定位目标即可。与虚拟机内存布局无关,引用目标不一定已经加载到虚拟机内存。

直接引用是可以直接指向目标的指针、相对偏移量或能间接定位到目标的句柄。和虚拟机的内存布局相关,引用目标必须已在虚拟机的内存中存在。

初始化

直到该阶段 JVM 才开始执行类中编写的代码。准备阶段时变量赋过零值,初始化阶段会根据程序员的编码去初始化类变量和其他资源。初始化阶段就是执行类构造方法中的 `` 方法,该方法是 Javac 自动生成的。

2、谈谈 JVM 中的常量池

JDK 1.8 开始

1、 字符串常量池:存放在堆中,包括 String 对象执行 intern() 方法后存的地方、双引号直接引用的字符串

2、 运行时常量池:存放在方法区,属于元空间,是类加载后的一些存储区域,大多数是类中 constant_pool 的内容

3、 类文件常量池:constant_pool,JVM 定义的概念

3、JVM 内存区域

JVM 内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区域【JAVA 堆、方法区】、直接内存。

线程私有数据区域生命周期与线程相同, 依赖用户线程的启动/结束 而 创建/销毁(在 Hotspot VM 内, 每个线程都与操作系统的本地线程直接映射, 因此这部分内存区域的存/否跟随本地线程的生/死对应)。

线程共享区域随虚拟机的启动/关闭而创建/销毁。

直接内存并不是 JVM 运行时数据区的一部分, 但也会被频繁的使用: 在 JDK 1.4 引入的 NIO 提供了基于Channel与 Buffer的IO方式, 它可以使用Native函数库直接分配堆外内存, 然后使用DirectByteBuffer 对象作为这块内存的引用进行操作(详见: Java I/O 扩展), 这样就避免了在 Java堆和 Native 堆中来回复制数据, 因此在一些场景中可以显著提高性能。

4、G1 收集器

Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与 CMS 收集器, G1 收集器两个最突出的改进是:

1、 基于标记-整理算法,不产生内存碎片。

2、 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间, 优先回收垃圾最多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收集效率

5、堆的作用是什么?

是虚拟机所管理的内存中最大的一块,被所有线程共享的,在虚拟机启动时创建。堆用来存放对象实例,Java 里几乎所有对象实例都在堆分配内存。堆可以处于物理上不连续的内存空间,逻辑上应该连续,但对于例如数组这样的大对象,多数虚拟机实现出于简单、存储高效的考虑会要求连续的内存空间。

堆既可以被实现成固定大小,也可以是可扩展的,可通过 -Xms-Xmx 设置堆的最小和最大容量,当前主流 JVM 都按照可扩展实现。如果堆没有内存完成实例分配也无法扩展,抛出 OutOfMemoryError。

6、如何查看 JVM 当前使用的是什么垃圾收集器?

-XX:+PrintCommandLineFlags 参数可以打印出所选垃圾收集器和堆空间大小等设置

如果开启了 GC 日志详细信息,里面也会包含各代使用的垃圾收集器的简称

7、GC的回收流程是怎样的?

GC回收流程如下:

1、 对于整个的GC流程里面,那么最需要处理的就是新生代和老年代的内存清理操作,而元空间(永久代)都不在GC范围内

2、 当现在有一个新的对象产生,那么对象一定需要内存空间,平均每个栈内存存4k,每个堆内存存8k,那么对象一定需要进行堆空间的申请

3、 首先会判断Eden区是否有内存空间,如果此时有内存空间,则直接将新对象保存在伊甸园区。

4、 但是如果此时在伊甸园区内存不足,那么会自动执行一个Minor GC 操作,将伊甸园区的无用内存空间进行清理,Minor GC的清理范围只在Eden园区,清理之后会继续判断Eden园区的内存空间是否充足?如果内存空间充足,则将新对象直接在Eden园区进行空间分配。

5、 如果执行Minor GC 之后发现伊甸园区的内存空间依然不足,那么这个时候会执行存活区的判断,如果存活区有剩余空间,则将Eden园区部分活跃对象保存在存活区,那么随后继续判断Eden园区的内存空间是否充足,如果充足怎则将新对象直接在Eden园区进行空间分配。

6、 此时如果存活区没有内存空间,则继续判断老年区。则将部分存活对象保存在老年代,而后存活区将有空余空间。

7、 如果这个时候老年代也满了,那么这个时候将产生Major GC(Full GC),那么这个时候将进行老年代的清理

8、 如果老年代执行Full GC之后,无法进行对象的保存,则会产生OOM异常,OutOfMemoryError异常

8、类的实例化顺序

1、 父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行

2、 子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行

3、 父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行

4、 父类构造方法

5、 子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行

6、 子类构造方法

检验一下是不是真懂了:

public class Base {
    private String name = "博客:Soinice";

    public Base() {
        tellName();
        printName();
    }

    public void tellName() {
        System.out.println("Base tell name: " + name);
    }

    public void printName() {
        System.out.println("Base print name: " + name);
    }
}
public class Dervied extends Base {
    private String name = "Java3y";

    public Dervied() {
        tellName();
        printName();
    }

    @Override
    public void tellName() {
        System.out.println("Dervied tell name: " + name);
    }

    @Override
    public void printName() {
        System.out.println("Dervied print name: " + name);
    }

    public static void main(String[] args) {
        new Dervied();
    }
}

输出数据:

Dervied tell name: null
Dervied print name: null
Dervied tell name: Java3y
Dervied print name: Java3y

Process finished with exit code 0

第一次做错的同学点个赞,加个关注不过分吧(hahaha。

9、工作中常用的 JVM 配置参数有哪些?

Java 8 为例

日志

1、 -XX:+PrintFlagsFinal,打印JVM所有参数的值

2、 -XX:+PrintGC,打印GC信息

3、 -XX:+PrintGCDetails,打印GC详细信息

4、 -XX:+PrintGCTimeStamps,打印GC的时间戳

5、 -Xloggc:filename,设置GC log文件的位置

6、 -XX:+PrintTenuringDistribution,查看熬过收集后剩余对象的年龄分布信息

内存设置

1、 -Xms,设置堆的初始化内存大小

2、 -Xmx,设置堆的最大内存

3、 -Xmn,设置新生代内存大小

4、 -Xss,设置线程栈大小

5、 -XX:NewRatio,新生代与老年代比值

6、 -XX:SurvivorRatio,新生代中Eden区与两个Survivor区的比值,默认为8,即Eden:Survivor:Survivor=8:1:1

7、 -XX:MaxTenuringThreshold,从年轻代到老年代,最大晋升年龄。CMS 下默认为 6,G1 下默认为 15

8、 -XX:MetaspaceSize,设置元空间的大小,第一次超过将触发 GC

9、 -XX:MaxMetaspaceSize,元空间最大值

10、 -XX:MaxDirectMemorySize,用于设置直接内存的最大值,限制通过 DirectByteBuffer 申请的内存

11、 -XX:ReservedCodeCacheSize,用于设置 JIT 编译后的代码存放区大小,如果观察到这个值有限制,可以适当调大,一般够用即可

设置垃圾收集相关

1、 -XX:+UseSerialGC,设置串行收集器

2、 -XX:+UseParallelGC,设置并行收集器

3、 -XX:+UseConcMarkSweepGC,使用CMS收集器

4、 -XX:ParallelGCThreads,设置Parallel GC的线程数

5、 -XX:MaxGCPauseMillis,GC最大暂停时间 ms

6、 -XX:+UseG1GC,使用G1垃圾收集器

CMS 垃圾回收器相关

1、 -XX:+UseCMSInitiatingOccupancyOnly

2、 -XX:CMSInitiatingOccupancyFraction,与前者配合使用,指定MajorGC的发生时机

3、 -XX:+ExplicitGCInvokesConcurrent,代码调用 System.gc() 开始并行 FullGC,建议加上这个参数

4、 -XX:+CMSScavengeBeforeRemark,表示开启或关闭在 CMS 重新标记阶段之前的清除(YGC)尝试,它可以降低 remark 时间,建议加上

5、 -XX:+ParallelRefProcEnabled,可以用来并行处理 Reference,以加快处理速度,缩短耗时

G1 垃圾回收器相关

1、 -XX:MaxGCPauseMillis,用于设置目标停顿时间,G1 会尽力达成

2、 -XX:G1HeapRegionSize,用于设置小堆区大小,建议保持默认

3、 -XX:InitiatingHeapOccupancyPercent,表示当整个堆内存使用达到一定比例(默认是 45%),并发标记阶段就会被启动

4、 -XX:ConcGCThreads,表示并发垃圾收集器使用的线程数量,默认值随 JVM 运行的平台不同而变动,不建议修改

参数查询官网地址:

https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

建议面试时最好能记住 CMS 和 G1的参数,特点突出使用较多,被问的概率大

10、Java里有哪些引用类型?

1、 强引用 这种引用属于最普通最强硬的一种存在,只有在和 GC Roots 断绝关系时,才会被消灭掉。

2、 软引用 软引用用于维护一些可有可无的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。可以看到,这种特性非常适合用在缓存技术上。比如网页缓存、图片缓存等。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java 虚拟机就会把这个软引用加入到与之关联的引用队列中。

3、 弱引用 弱引用对象相比较软引用,要更加无用一些,它拥有更短的生命周期。当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。弱引用拥有更短的生命周期,在 Java 中,用 java.lang.ref.WeakReference 类来表示。它的应用场景和软引用类似,可以在一些对内存更加敏感的系统里采用。

4、 虚引用 这是一种形同虚设的引用,在现实场景中用的不是很多。虚引用必须和引用队列(ReferenceQueue)联合使用。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。实际上,虚引用的 get,总是返回 null。

11、本地方法区(线程私有)

12、什么是本地方法栈

13、栈溢出的原因?

14、Java的内存模型是什么?(JMM是什么?)

15、方法区溢出的原因?

16、JVM 监控与分析工具你用过哪些?介绍一下。

17、说说类加载的过程

18、MinorGC、MajorGC、FullGC 什么时候发生?

19、谈谈你知道的垃圾收集器

20、复制算法(copying)

21、垃圾收集算法

22、JVM的永久代中会发生垃圾回收么

23、类加载器双亲委派模型机制?

24、为什么需要双亲委派模式?

25、讲讲什么情况下会出现内存溢出,内存泄漏?

26、JVM 如何确定垃圾对象?

27、OSGI( 动态模型系统)

28、你平时工作中用过的JVM常用基本配置参数有哪些?

29、invokedynamic指令是干什么的?

30、程序计数器

31、强引用、软引用、弱引用、虚引用是什么?

全部答案,更新日期:12月29日,直接下载吧!

下载链接:全部答案,整理好了

新增:高清PDF:172份,7701页,最新整理

大厂面试题

大厂面试题

Java
1
https://gitee.com/souyunku/DevBooks.git
git@gitee.com:souyunku/DevBooks.git
souyunku
DevBooks
DevBooks
master

Search