更新時間:2023-01-30 15:05:54 來源:動力節點 瀏覽1957次
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面試題相關內容,可以關注動力節點Java官網。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習