更新时间:2023-01-30 15:05:54 来源:极悦 浏览1162次
JVM性能调优是一个很大的话题,很多中小企业的业务规模受限,没有迫切的性能调优需求,但是如果不知道JVM相关的理论知识,写出来的代码或者配置的JVM参数不合理时,就会出现很严重的性能问题,到时候开发就会像热锅上的蚂蚁,等待各方的炙烤。今天小编总结了一些相关的面试题,一是希望能够应对性能调优岗位相关的面试;二是希望总结一下具体的实战步骤,并努力吸收书中的实践案例,让自己的经验更丰富一些。
JVM性能调优
内存溢出错误
学习目的:
通过异常信息及时定位到发生内存溢出的运行时数据区域
了解什么样的代码会导致内存溢出,防止写出这样的代码
出现异常后该如何处理,也就是学习事中的处理手段
内存溢出和内存泄露的区别
内存泄露:不该留存在进程中的内存数据,虽然很小,但是在经过多次长期的积累后,会导致内存溢出
内存溢出:程序申请内存时,内存不足的现象
堆溢出错误和预判堆溢出的错误
如何复现出堆溢出错误?
JVM参数部分:最大堆和最小堆设置相同并且设置的比较小,比如只有10M,这样就不会自动扩展堆
代码部分:在一个方法中不断地往集合中加入元素
代码实践
package org.example;
import java.util.ArrayList;
import java.util.List;
/**
* -Xmx10M -Xms10M -XX:+HeapDumpOnOutOfMemoryError
*/
public class App {
static class OOMObject {
int a = 1;
long b = 2;
float c = 2.1f;
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while (true) {
list.add(new OOMObject());
}
}
}
正确的出现了我们想要的结果:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid24476.hprof ...
Heap dump file created [13268403 bytes in 0.077 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at org.example.App.main(App.java:22)
Process finished with exit code 1
如果把参数调大,调整20M,那么会报另外的error
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to java_pid8796.hprof ...
Heap dump file created [27391983 bytes in 0.141 secs]
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.example.App.main(App.java:19)
Process finished with exit code 1
这个错误的原因是,JVMGC时间占据了整个运行时间的98%,但是回收只得到了2%可用的内存,至少出现5次,就会报这个异常。
这个异常是Jdk1.6定义的策略, 通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。
案例心得:
虚拟机栈和本地方法栈溢出错误
一般我们会遇到两种栈相关的错误:
单个线程中,不断的调用方法入栈,当栈深度超过虚拟机所允许的最大深度时,抛出StackOverflowError
不断地创建线程,创建线程就需要创建栈,当无法申请到足够的内存,就会报 unable to create new native thread错误
如何复现?
JVM参数:-Xss128k,每个线程的栈内存大小
代码部分:没有出口的递归调用
代码实践
/**
* -Xss128k
*/
public class App {
static int length = 0;
private static void reverse() {
length++;
reverse();
}
public static void main(String[] args) {
try {
reverse();
} catch (Throwable e) {
System.out.println("length:" + length);
throw e;
}
}
}
结果验证:
length:1096
Exception in thread "main" java.lang.StackOverflowError
at org.example.App.reverse(App.java:10)
at org.example.App.reverse(App.java:11)
at org.example.App.reverse(App.java:11)
at org.example.App.reverse(App.java:11)
太多了,这里只截取部分
关于unable to create new native thread这个异常,这里就不尝试了,因为可能会导致操作系统假死等问题。
案例心得:
以上就是“比较经典的一些jvm调优策略面试题”,你能回答上来吗?如果想要了解更多的相关内容,可以关注极悦Java官网。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习