如何开启jvm日志_「技术干货」JVM经典面试题集锦

1. JVM参数主要有几种分类?

标准参数

标准参数,顾名思义,标准参数中包括功能以及输出的结果都是很稳定的,基本上不会随着JVM版本的 变化而变化。标准参数以-开头,如:java -version、java -jar等,通过java -help可以查询所有的标准参数。

非标准参数

非标准参数以-X开头,是标准参数的扩展。对应前⾯讲的标准化参数,这是非标准化参数。表示在将来 的JVM版本中可能会发生改变,但是这类以-X开始的参数变化的⽐较小。

不稳定参数

这是我们日常开发中接触到最多的参数类型。这也是⾮标准化参数,相对来说不稳定,随着JVM版本的 变化可能会发生变化,主要用于JVM调优和debug。

不稳定参数以-XX 开头,此类参数的设置很容易引起JVM 性能上的差异,使JVM存在极大的不稳定性。如果此类参数设置合理将大大提⾼JVM 的性能及稳定性。

不稳定参数分为三类:

性能参数:用于JVM的性能调优和内存分配控制,如内存大小的设置;

行为参数:用于改变JVM的基础行为,如GC的⽅式和算法的选择;

调试参数:用于监控、打印、输出jvm的信息;

2. Java中会存在内存泄漏吗,简述一下。

理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程 的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因 此也会导致内存泄露的发生。例如hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器 是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露。下面例子中的代码也会导致内存泄露。

3. Java 中都有哪些引用类型?

强引用:发生 gc 的时候不会被回收。new。

软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。SoftReference

弱引用:有用但不是必须的对象,在下一次GC时会被回收。WeakReference

虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。

4. 在 Java 中,对象什么时候可以被垃圾回收?

首先先由可达性算法去判断对象是否可回收二次标记,相当于二次审判。finalize方法其次再去根据GC的回收机制,择时回收

5. StackOverflow异常有没有遇到过?一般你猜测会在什么情况下被触发?

栈内存溢出,一般由栈内存的局部变量过大,导致内存溢出。出现在递归方法,参数个数过多, 递归过深,递归没有出口。

6. 堆空间分哪⼏个部分?以及如何设置各个部分大小?

Java堆被所有线程共享,在Java虚拟机启动时创建。是虚拟机管理最大的⼀块内存。

Java堆是垃圾回收的主要区域,而且主要采用分代回收算法。堆进⼀步划分主要是为了更好的回收内存 或更快地分配内存。

Java虚拟机规范的描述是:所有的对象实例以及数组都要在堆上分配。堆内存空间在物理上可以不连续,逻辑上连续即可。

堆大小 = 新生代 + ⽼年代。

堆的大小可通过参数 –Xms(堆的初始容量)、-Xmx(堆的最大容量) 来指定。

其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为

from 和 to,以示区分。

默认的,Eden : from : to = 8 : 1 : 1 。(可以通过参数 –XX:SurvivorRatio 来设定 。) 即:Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。

JVM 每次只会使用 Eden 和其中的⼀块 Survivor 区域来为对象服务,所以⽆论什么时候,总是有⼀块

Survivor 区域是空闲着的。

新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

-Xmn:⾄于这个参数则是对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过- Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn,虽然会很⽅便,但需要注意的是这个参数是在JDK1.4版本以后才使用的。

7495e64bacb73903ba74620c3ab0de8d.png

7. 什么是栈帧?栈帧存储了什么?

虚拟机栈也是线程私有,而且生命周期与线程相同,每个Java⽅法在执⾏的时候都会创建⼀个栈帧(Stack Frame)。栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构。栈帧存储了⽅法的局部变量表、操作数栈、动态连接和⽅法返回地址等信息。每⼀个⽅法从调用至执行完成的过程,都对应一个栈帧在虚拟机栈⾥从⼊栈到出栈的过程。

8. 如何设置参数生成GC日志?

设置JVM

GC格式日志的主要参数包括如下8个:

1. -XX:+PrintGC 输出简要GC日志。

2. -XX:+PrintGCDetails 输出详细GC日志。

3. -Xloggc:gc.log 输出GC日志到⽂件。

4. -XX:+PrintGCTimeStamps 输出GC的时间戳(以JVM启动到当期的总时⻓的时间戳形式)。

5. -XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2020-04- 26T21:53:59.234+0800)。

6. -XX:+PrintHeapAtGC 在进⾏GC的前后打印出堆的信息。

7. -verbose:gc : 在JDK 8中, -verbose:gc 是 -XX:+PrintGC ⼀个别称,日志格式等价与:- XX:+PrintGC 。不过在JDK 9中 -XX:+PrintGC被标记为deprecated。

-verbose:gc是⼀个标准的选项,-XX:+PrintGC是⼀个实验的选项,建议使用-verbose:gc 替代 - XX:+PrintGC。

8. -XX:+PrintReferenceGC 打印年轻代各个引用的数量以及时⻓。

开启GC日志

多种⽅法都能开启GC的日志功能,其中包括:使用-verbose:gc或-XX:+PrintGC这两个标志中的任意⼀ 个能创建基本的GC日志(这两个日志标志实际上互为别名,默认情况下的GC日志功能是关闭的)使用XX:+PrintGCDetails标志会创建更详细的GC日志推荐使用-XX:+PrintGCDetails标志(这个标志默认情况 下也是关闭的);通常情况下使用基本的GC日志很难诊断垃圾回收时发生的问题。

开启GC时间提示

除了使用详细的GC日志,我们还推荐使用-XX:+PrintGCTimeStamps或者-XX:+PrintGCDateStamps, 便于我们更精确地判断⼏次GC操作之间的时间。这两个参数之间的差别在于时间戳是相对于0(依据 JVM启动的时间)的值,而日期戳(date stamp)是实际的日期字符串。由于日期戳需要进⾏格式化, 所以它的效率可能会受轻微的影响,不过这种操作并不频繁,它造成的影响也很难被我们感知。

指定GC日志路径

默认情况下GC日志直接输出到标准输出,不过使用-Xloggc:filename标志也能修改输出到某个⽂件。除⾮显式地使用-PrintGCDetails标志,否则使用-Xloggc会⾃动地开启基本日志模式。使用日志循环(Log rotation)标志可以限制保存在GC日志中的数据量;对于需要⻓时间运⾏的服务器而⾔,这是⼀个⾮常 有用的标志,否则累积⼏个⽉的数据很可能会耗尽服务器的磁盘。

开启日志滚动输出

通过-XX:+UseGCLogfileRotation -XX:NumberOfGCLogfiles=N -XX:GCLogfileSize=N标志可以控制日志⽂件的循环。默认情况下,UseGCLogfileRotation标志是关闭的。它负责打开或关闭GC日志滚动记 录功能的。要求必须设置 -Xloggc参数开启UseGCLogfileRotation标志后,默认的⽂件数⽬是0(意味着不作任何限制),默认的日志⽂件大小是0(同样也是不作任何限制)。因此,为了让日志循环功能 真正生效,我们必须为所有这些标志设定值。

需要注意的是:

The size of the log file at which point the log will be rotated, must be >= 8K. 设置滚动日志⽂件的大小,必须大于8k。当前写日志⽂件大小超过该参数值时,日志将写⼊下⼀个⽂件设置滚动日志⽂件的个 数,必须大于等于1必须设置 -Xloggc 参数。

9. GC 是什么?为什么要有 GC?

GC 是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。Java 程序员不用担心内存管理, 因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但 JVM 可以屏蔽掉显示的垃圾回收调用。

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低 优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回 收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在 Java 诞生初期,垃圾回收是 Java 最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今 Java 的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得 iOS 的系统比 Android 系统有更好的用户体验,其中一个深层次的原因就在于 Android 系统中垃圾回收的不可预知性。

10.第 3 行中生成的 object在第几行执行后成为 garbage collection 的对象?

public class MyClass {    public StringBuffer aMethod() {        StringBuffer sf = new StringBuffer(“Hello”);        StringBuffer[] sf_arr = new StringBuffer[1];        sf_arr[0] = sf;        sf = null;        sf_arr[0] = null;        return sf;    }}

第 7 行。

11. Java 虚拟机是如何判定两个 Java 类是相同的?

①类的全限定名是否相等。

②类加载器是否相等。

即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。比如一个 Java 类com.example.Sample,编译之后生成了字节代码文件 Sample.class。两个不同的类加载器ClassLoaderA和 ClassLoaderB分别读取了这个 Sample.class文件,并定义出两个 java.lang.Class类的实例来表示这个类。这两个实例是不相同的。对于 Java 虚拟机来说,它们是不同的类。

12. 使用过哪些jdk命令,并说明各自的作用是什么?

  • jps

jps:Java Virtual Machine Process Status Tool

查看Java进程,相当于Linux下的ps命令,只不过它只列出Java进程。

  • jstat

jstat:JVM Statistics Monitoring Tool

jstat可以查看Java程序运行时相关信息,可以通过它查看堆信息的相关情况。

  • jinfo

jinfo:Java Configuration Info

jinfo可以用来查看正在运⾏的java程序的扩展参数,甚至支持运行时,修改部分参数。

  • jmap

jmap:Memory Map

jmap用来查看堆内存使用状况,一般结合 jhat 使用。

  • jstack

jstack:Java Stack Trace,jstack是java虚拟机⾃带的⼀种堆栈跟踪⼯具。jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每⼀条线程正在执行方法的堆栈的集合,生成线 程快照的主要⽬的是定位线程出现⻓时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的⻓ 时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core⽂件,jstack⼯具可以用来获得core⽂件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运⾏的java程序中,看到当时运⾏的java程序的java stack和native stack的信息, 如果现在运⾏的java程序呈现hung的状态,jstack是⾮常有用的。

  • jconsole

Jconsole:Java Monitoring and Management Console,Java 5 引入,一个内置 Java 性能分析器, 可以从命令⾏或在 GUI shell 中运⾏。您可以轻松地使用 JConsole来监控 Java 应用程序性能和跟踪Java 中的代码。

cf0d0d5a13b3d848baac8b09f21aac86.png

13. JVM运⾏时数据区区域分为哪⼏部分?

线程共享:堆、方法区。

线程私有:虚拟机栈、本地方法栈、程序计数器。

jdk1.7之前,HotSpot虚拟机对于⽅法区的实现称之为“永久代”, Permanent Generation.

jdk1.8之后,HotSpot虚拟机对于⽅法区的实现称之为“元空间”, Meta Space.

⽅法区是Java虚拟机规范中的定义,是⼀种规范,而永久代和元空间是 HotSpot 虚拟机不同版本的两种实现。

14. 是否了解类加载器双亲委派模型机制和破坏双亲委派模型?

双亲委派模型机制:皇子的例子。

破坏双亲委派模型:JDK1.0的时候写好了一些类和类加载器,但是JDK1.2的时候才出现了双亲委派模 型。比如说DriverManager去加载Driver的时候,就是破坏了双亲委派模型。

DriverManager相当于是皇上去处理。

Driver实现类(第三方提供)相当于皇子去处理。

15. 逃逸分析有⼏种类型?

逃逸分析(Escape Analysis)是⽬前Java虚拟机中⽐较前沿的优化技术。这是⼀种可以有效减少Java 程序中同步负载和内存堆分配压⼒的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出⼀个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。

逃逸分析的基本行为就是分析对象动态作用域:当⼀个对象在⽅法中被定义后,它可能被外部⽅法所引用,例如作为调用参数传递到其他地⽅中,称为⽅法逃逸。逃逸分析包括:

全局变量赋值逃逸

方法返回值逃逸

实例引用发生逃逸

线程逃逸:赋值给类变量或可以在其他线程中访问的实例变量

16.-Xms这些参数的含义是什么?

堆内存分配:

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64。

JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。

17. 你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包括原理,流程,优缺点。

几种垃圾收集器:

Serial收集器:单线程的收集器,收集垃圾时,必须stoptheworld,使用复制算法。ParNew收集器:Serial收集器的多线程版本,也需要stoptheworld,复制算法。

ParallelScavenge收集器:新生代收集器,复制算法的收集器,并发的多线程收集器,目标是达到一个 可控的吞吐量。如果虚拟机总共运行100分钟,其中垃圾花掉1分钟,吞吐量就是99%。

SerialOld收集器:是Serial收集器的老年代版本,单线程收集器,使用标记整理算法。

ParallelOld收集器:是ParallelScavenge收集器的老年代版本,使用多线程,标记-整理算法。

CMS(ConcurrentMarkSweep)收集器:是一种以获得最短回收停顿时间为目标的收集器,标记清除算法,运作过程:初始标记,并发标记,重 新标记,并发清除,收集结束会产生大量空间碎片。

G1收集器:标记整理算法实现,运作流程主要包括以下:初始标记,并发标记,最终标记,筛选标记。 不会产生空间碎片,可以精确地控制停顿。

CMS收集器和G1收集器的区别:CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收 集器一起使用;G1收集器收集范围是老年代和新生代,不需要结合其他收集器使用;CMS收集器以最 小的停顿时间为目标的收集器;G1收集器可预测垃圾回收的停顿时间CMS收集器是使用“标记-清除”算 法进行的垃圾回收,容易产生内存碎片G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。

18. JVM的内存结构,Eden和Survivor比例是多少?

Eden区是一块,Survivor区是两块。

Eden区和Survivor区的比例是8:1:1。

5937b80fecba330306bb3e8d176f3877.png

总结

以上就是今天的内容了,如果对你有帮助,希望你能够关注、点赞、转发一键三连支持一下。

以上内容希望对你有用,如果有大数据方面的问题,欢迎关注我并向我私信,评论,需要学习线路图,评论区回复111。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值