更新時(shí)間:2023-01-30 15:05:54 來源:動(dòng)力節(jié)點(diǎn) 瀏覽2875次
JVM性能調(diào)優(yōu)是一個(gè)很大的話題,很多中小企業(yè)的業(yè)務(wù)規(guī)模受限,沒有迫切的性能調(diào)優(yōu)需求,但是如果不知道JVM相關(guān)的理論知識(shí),寫出來的代碼或者配置的JVM參數(shù)不合理時(shí),就會(huì)出現(xiàn)很嚴(yán)重的性能問題,到時(shí)候開發(fā)就會(huì)像熱鍋上的螞蟻,等待各方的炙烤。今天小編總結(jié)了一些相關(guān)的面試題,一是希望能夠應(yīng)對(duì)性能調(diào)優(yōu)崗位相關(guān)的面試;二是希望總結(jié)一下具體的實(shí)戰(zhàn)步驟,并努力吸收書中的實(shí)踐案例,讓自己的經(jīng)驗(yàn)更豐富一些。

JVM性能調(diào)優(yōu)
內(nèi)存溢出錯(cuò)誤
學(xué)習(xí)目的:
通過異常信息及時(shí)定位到發(fā)生內(nèi)存溢出的運(yùn)行時(shí)數(shù)據(jù)區(qū)域
了解什么樣的代碼會(huì)導(dǎo)致內(nèi)存溢出,防止寫出這樣的代碼
出現(xiàn)異常后該如何處理,也就是學(xué)習(xí)事中的處理手段
內(nèi)存溢出和內(nèi)存泄露的區(qū)別
內(nèi)存泄露:不該留存在進(jìn)程中的內(nèi)存數(shù)據(jù),雖然很小,但是在經(jīng)過多次長(zhǎng)期的積累后,會(huì)導(dǎo)致內(nèi)存溢出
內(nèi)存溢出:程序申請(qǐng)內(nèi)存時(shí),內(nèi)存不足的現(xiàn)象
堆溢出錯(cuò)誤和預(yù)判堆溢出的錯(cuò)誤
如何復(fù)現(xiàn)出堆溢出錯(cuò)誤?
JVM參數(shù)部分:最大堆和最小堆設(shè)置相同并且設(shè)置的比較小,比如只有10M,這樣就不會(huì)自動(dòng)擴(kuò)展堆
代碼部分:在一個(gè)方法中不斷地往集合中加入元素
代碼實(shí)踐
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());
}
}
}
正確的出現(xiàn)了我們想要的結(jié)果:
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
如果把參數(shù)調(diào)大,調(diào)整20M,那么會(huì)報(bào)另外的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
這個(gè)錯(cuò)誤的原因是,JVMGC時(shí)間占據(jù)了整個(gè)運(yùn)行時(shí)間的98%,但是回收只得到了2%可用的內(nèi)存,至少出現(xiàn)5次,就會(huì)報(bào)這個(gè)異常。
這個(gè)異常是Jdk1.6定義的策略, 通過統(tǒng)計(jì)GC時(shí)間來預(yù)測(cè)是否要OOM了,提前拋出異常,防止OOM發(fā)生。
案例心得:
虛擬機(jī)棧和本地方法棧溢出錯(cuò)誤
一般我們會(huì)遇到兩種棧相關(guān)的錯(cuò)誤:
單個(gè)線程中,不斷的調(diào)用方法入棧,當(dāng)棧深度超過虛擬機(jī)所允許的最大深度時(shí),拋出StackOverflowError
不斷地創(chuàng)建線程,創(chuàng)建線程就需要?jiǎng)?chuàng)建棧,當(dāng)無法申請(qǐng)到足夠的內(nèi)存,就會(huì)報(bào) unable to create new native thread錯(cuò)誤
如何復(fù)現(xiàn)?
JVM參數(shù):-Xss128k,每個(gè)線程的棧內(nèi)存大小
代碼部分:沒有出口的遞歸調(diào)用
代碼實(shí)踐
/**
* -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;
}
}
}
結(jié)果驗(yàn)證:
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)
太多了,這里只截取部分
關(guān)于unable to create new native thread這個(gè)異常,這里就不嘗試了,因?yàn)榭赡軙?huì)導(dǎo)致操作系統(tǒng)假死等問題。
案例心得:
以上就是“比較經(jīng)典的一些jvm調(diào)優(yōu)策略面試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關(guān)內(nèi)容,可以關(guān)注動(dòng)力節(jié)點(diǎn)Java官網(wǎng)。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)