(說明:這一塊原本要總結,可是在github上有一份比較全,比較精華的總結,就貼過來了,整個系列缺了各類垃圾回收器和三色標記算法的一個詳細解釋,後期補上。原文地址:github.com/bjmashibing…)html
C語言申請內存:malloc freejava
C++: new deletelinux
c/C++ 手動回收內存nginx
Java: new ?git
自動內存回收,編程上簡單,系統不容易出錯,手動釋放內存,容易出兩種類型的問題:程序員
- 忘記回收
- 屢次回收
沒有任何引用指向的一個對象或者多個對象(循環引用)github
部分垃圾回收器使用的模型面試
除Epsilon ZGC Shenandoah以外的GC都是使用邏輯分代模型redis
G1是邏輯分代,物理不分代算法
除此以外不只邏輯分代,並且物理分代
新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元數據區(1.8) Metaspace
新生代 = Eden + 2個suvivor區
老年代
GC Tuning (Generation)
動態年齡:(不重要) www.jianshu.com/p/989d3b06a…
分配擔保:(不重要) YGC期間 survivor區空間不夠了 空間擔保直接進入老年代 參考:cloud.tencent.com/developer/a…
1.8默認的垃圾回收:PS + ParallelOld
-XX:+UseSerialGC = Serial New (DefNew) + Serial Old
-XX:+UseParNewGC = ParNew + SerialOld
-XX:+UseConc(urrent)MarkSweepGC = ParNew + CMS + Serial Old
-XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默認) 【PS + SerialOld】
-XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old
-XX:+UseG1GC = G1
Linux中沒找到默認GC的查看方法,而windows中會打印UseParallelGC
Linux下1.8版本默認的垃圾回收器究竟是什麼?
JVM的命令行參數參考:docs.oracle.com/javase/8/do…
HotSpot參數分類
標準: - 開頭,全部的HotSpot都支持
非標準:-X 開頭,特定版本HotSpot支持特定命令
不穩定:-XX 開頭,下個版本可能取消
java -version
java -X
試驗用程序:
import java.util.List;
import java.util.LinkedList;
public class HelloGC {
public static void main(String[] args) {
System.out.println("HelloGC!");
List list = new LinkedList();
for(;;) {
byte[] b = new byte[1024*1024];
list.add(b);
}
}
}複製代碼
每種垃圾回收器的日誌格式是不一樣的!
PS日誌格式
heap dump部分:
eden space 5632K, 94% used [0x00000000ff980000,0x00000000ffeb3e28,0x00000000fff00000)
後面的內存地址指的是,起始地址,使用空間結束地址,總體空間結束地址複製代碼
total = eden + 1個survivor
所謂調優,首先肯定,追求啥?吞吐量優先,仍是響應時間優先?仍是在知足必定的響應時間的狀況下,要求達到多大的吞吐量...
問題:
科學計算,吞吐量。數據挖掘,thrput。吞吐量優先的通常:(PS + PO)
響應時間:網站 GUI API (1.8 G1)
調優,從業務場景開始,沒有業務場景的調優都是耍流氓
無監控(壓力測試,能看到結果),不調優
步驟:
案例1:垂直電商,最高每日百萬訂單,處理訂單系統須要什麼樣的服務器配置?
這個問題比較業餘,由於不少不一樣的服務器配置都能支撐(1.5G 16G)
1小時360000集中時間段, 100個訂單/秒,(找一小時內的高峯期,1000訂單/秒)
經驗值,
非要計算:一個訂單產生須要多少內存?512K * 1000 500M內存
專業一點兒問法:要求響應時間100ms
壓測!
案例2:12306遭遇春節大規模搶票應該如何支撐?
12306應該是中國併發量最大的秒殺網站:
號稱併發量100W最高
CDN -> LVS -> NGINX -> 業務系統 -> 每臺機器1W併發(10K問題) 100臺機器
普通電商訂單 -> 下單 ->訂單系統(IO)減庫存 ->等待用戶付款
12306的一種可能的模型: 下單 -> 減庫存 和 訂單(redis kafka) 同時異步進行 ->等付款
減庫存最後還會把壓力壓到一臺服務器
能夠作分佈式本地庫存 + 單獨服務器作庫存均衡
大流量的處理方法:分而治之
怎麼獲得一個事務會消耗多少內存?
弄臺機器,看能承受多少TPS?是否是達到目標?擴容或調優,讓它達到
用壓測來肯定
測試代碼:
package com.mashibing.jvm.gc;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 從數據庫中讀取信用數據,套用模型,並把結果進行記錄和傳輸
*/
public class T15_FullGC_Problem01 {
private static class CardInfo {
BigDecimal price = new BigDecimal(0.0);
String name = "張三";
int age = 5;
Date birthdate = new Date();
public void m() {}
}
private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50,
new ThreadPoolExecutor.DiscardOldestPolicy());
public static void main(String[] args) throws Exception {
executor.setMaximumPoolSize(50);
for (;;){
modelFit();
Thread.sleep(100);
}
}
private static void modelFit(){
List<CardInfo> taskList = getAllCardInfo();
taskList.forEach(info -> {
// do something
executor.scheduleWithFixedDelay(() -> {
//do sth with info
info.m();
}, 2, 3, TimeUnit.SECONDS);
});
}
private static List<CardInfo> getAllCardInfo(){
List<CardInfo> taskList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
CardInfo ci = new CardInfo();
taskList.add(ci);
}
return taskList;
}
}
複製代碼
java -Xms200M -Xmx200M -XX:+PrintGC com.mashibing.jvm.gc.T15_FullGC_Problem01
通常是運維團隊首先受到報警信息(CPU Memory)
top命令觀察到問題:內存不斷增加 CPU佔用率居高不下
top -Hp 觀察進程中的線程,哪一個線程CPU和內存佔比高
jps定位具體java進程 jstack 定位線程情況,重點關注:WAITING BLOCKED eg. waiting on <0x0000000088ca3310> (a java.lang.Object) 假若有一個進程中100個線程,不少線程都在waiting on ,必定要找到是哪一個線程持有這把鎖 怎麼找?搜索jstack dump的信息,找 ,看哪一個線程持有這把鎖RUNNABLE 做業:1:寫一個死鎖程序,用jstack觀察 2 :寫一個程序,一個線程持有鎖不釋放,其餘線程等待
爲何阿里規範裏規定,線程的名稱(尤爲是線程池)都要寫有意義的名稱 怎麼樣自定義線程池裏的線程名稱?(自定義ThreadFactory)
jinfo pid
jstat -gc 動態觀察gc狀況 / 閱讀GC日誌發現頻繁GC / arthas觀察 / jconsole/jvisualVM/ Jprofiler(最好用) jstat -gc 4655 500 : 每一個500個毫秒打印GC的狀況 若是面試官問你是怎麼定位OOM問題的?若是你回答用圖形界面(錯誤) 1:已經上線的系統不用圖形界面用什麼?(cmdline arthas) 2:圖形界面到底用在什麼地方?測試!測試的時候進行監控!(壓測觀察)
jmap - histo 4655 | head -20,查找有多少對象產生
jmap -dump:format=b,file=xxx pid :
線上系統,內存特別大,jmap執行期間會對進程產生很大影響,甚至卡頓(電商不適合) 1:設定了參數HeapDump,OOM的時候會自動產生堆轉儲文件 2:不少服務器備份(高可用),停掉這臺服務器對其餘服務器不影響 3:在線定位(通常小點兒公司用不到)
java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError com.mashibing.jvm.gc.T15_FullGC_Problem01
使用MAT / jhat /jvisualvm 進行dump文件分析 www.cnblogs.com/baihuitests… jhat -J-mx512M xxx.dump http://192.168.17.11:7000 拉到最後:找到對應連接 可使用OQL查找特定問題對象
找到代碼的問題
程序啓動加入參數:
java -Djava.rmi.server.hostname=192.168.17.11 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=11111 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false XXX複製代碼
若是遭遇 Local host name unknown:XXX的錯誤,修改/etc/hosts文件,把XXX加入進去
192.168.17.11 basic localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6複製代碼
關閉linux防火牆(實戰中應該打開對應端口)
service iptables stop chkconfig iptables off #永久關閉複製代碼
windows上打開 jconsole遠程鏈接 192.168.17.11:11111
www.cnblogs.com/liugh/p/762… (簡單作法)
Memory Fragmentation
-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction 默認爲0 指的是通過多少次FGC才進行壓縮
Floating Garbage
Concurrent Mode Failure 產生:if the concurrent collector is unable to finish reclaiming the unreachable objects before the tenured generation fills up, or if an allocation cannot be satisfiedwith the available free space blocks in the tenured generation, then theapplication is paused and the collection is completed with all the applicationthreads stopped
解決方案:下降觸發CMS的閾值
PromotionFailed
解決方案相似,保持老年代有足夠的空間
–XX:CMSInitiatingOccupancyFraction 92% 能夠下降這個值,讓CMS保持老年代足夠的空間
執行命令:java -Xms20M -Xmx20M -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC com.mashibing.jvm.gc.T15_FullGC_Problem01
[GC (Allocation Failure) [ParNew: 6144K->640K(6144K), 0.0265885 secs] 6585K->2770K(19840K), 0.0268035 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
ParNew:年輕代收集器
6144->640:收集先後的對比
(6144):整個年輕代容量
6585 -> 2770:整個堆的狀況
(19840):整個堆大小
[GC (CMS Initial Mark) [1 CMS-initial-mark: 8511K(13696K)] 9866K(19840K), 0.0040321 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
//8511 (13696) : 老年代使用(最大)
//9866 (19840) : 整個堆使用(最大)
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.018/0.018 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
//這裏的時間意義不大,由於是併發執行
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//標記Card爲Dirty,也稱爲Card Marking
[GC (CMS Final Remark) [YG occupancy: 1597 K (6144 K)][Rescan (parallel) , 0.0008396 secs][weak refs processing, 0.0000138 secs][class unloading, 0.0005404 secs][scrub symbol table, 0.0006169 secs][scrub string table, 0.0004903 secs][1 CMS-remark: 8511K(13696K)] 10108K(19840K), 0.0039567 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//STW階段,YG occupancy:年輕代佔用及容量
//[Rescan (parallel):STW下的存活對象標記
//weak refs processing: 弱引用處理
//class unloading: 卸載用不到的class
//scrub symbol(string) table:
//cleaning up symbol and string tables which hold class-level metadata and
//internalized string respectively
//CMS-remark: 8511K(13696K): 階段事後的老年代佔用及容量
//10108K(19840K): 階段事後的堆佔用及容量
[CMS-concurrent-sweep-start]
[CMS-concurrent-sweep: 0.005/0.005 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
//標記已經完成,進行併發清理
[CMS-concurrent-reset-start]
[CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
//重置內部結構,爲下次GC作準備複製代碼
[GC pause (G1 Evacuation Pause) (young) (initial-mark), 0.0015790 secs]
//young -> 年輕代 Evacuation-> 複製存活對象
//initial-mark 混合回收的階段,這裏是YGC混合老年代回收
[Parallel Time: 1.5 ms, GC Workers: 1] //一個GC線程
[GC Worker Start (ms): 92635.7]
[Ext Root Scanning (ms): 1.1]
[Update RS (ms): 0.0]
[Processed Buffers: 1]
[Scan RS (ms): 0.0]
[Code Root Scanning (ms): 0.0]
[Object Copy (ms): 0.1]
[Termination (ms): 0.0]
[Termination Attempts: 1]
[GC Worker Other (ms): 0.0]
[GC Worker Total (ms): 1.2]
[GC Worker End (ms): 92636.9]
[Code Root Fixup: 0.0 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 0.0 ms]
[Other: 0.1 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 0.0 ms]
[Ref Enq: 0.0 ms]
[Redirty Cards: 0.0 ms]
[Humongous Register: 0.0 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 0.0 ms]
[Eden: 0.0B(1024.0K)->0.0B(1024.0K) Survivors: 0.0B->0.0B Heap: 18.8M(20.0M)->18.8M(20.0M)]
[Times: user=0.00 sys=0.00, real=0.00 secs]
//如下是混合回收其餘階段
[GC concurrent-root-region-scan-start]
[GC concurrent-root-region-scan-end, 0.0000078 secs]
[GC concurrent-mark-start]
//沒法evacuation,進行FGC
[Full GC (Allocation Failure) 18M->18M(20M), 0.0719656 secs]
[Eden: 0.0B(1024.0K)->0.0B(1024.0K) Survivors: 0.0B->0.0B Heap: 18.8M(20.0M)->18.8M(20.0M)], [Metaspace: 38
76K->3876K(1056768K)] [Times: user=0.07 sys=0.00, real=0.07 secs]
複製代碼
OOM產生的緣由多種多樣,有些程序未必產生OOM,不斷FGC(CPU飆高,但內存回收特別少) (上面案例)
硬件升級系統反而卡頓的問題(見上)
線程池不當運用產生OOM問題(見上) 不斷的往List里加對象(實在太LOW)
smile jira問題 實際系統不斷重啓 解決問題 加內存 + 更換垃圾回收器 G1 真正問題在哪兒?不知道
tomcat http-header-size過大問題(Hector)
lambda表達式致使方法區溢出問題(MethodArea / Perm Metaspace) LambdaGC.java -XX:MaxMetaspaceSize=9M -XX:+PrintGCDetails
"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" -XX:MaxMetaspaceSize=9M -XX:+PrintGCDetails "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\lib\idea_rt.jar=49316:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;C:\work\ijprojects\JVM\out\production\JVM;C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar" com.mashibing.jvm.gc.LambdaGC
[GC (Metadata GC Threshold) [PSYoungGen: 11341K->1880K(38400K)] 11341K->1888K(125952K), 0.0022190 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Metadata GC Threshold) [PSYoungGen: 1880K->0K(38400K)] [ParOldGen: 8K->1777K(35328K)] 1888K->1777K(73728K), [Metaspace: 8164K->8164K(1056768K)], 0.0100681 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Last ditch collection) [PSYoungGen: 0K->0K(38400K)] 1777K->1777K(73728K), 0.0005698 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Last ditch collection) [PSYoungGen: 0K->0K(38400K)] [ParOldGen: 1777K->1629K(67584K)] 1777K->1629K(105984K), [Metaspace: 8164K->8156K(1056768K)], 0.0124299 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:388)
at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:411)
Caused by: java.lang.OutOfMemoryError: Compressed class space
at sun.misc.Unsafe.defineClass(Native Method)
at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:63)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394)
at java.security.AccessController.doPrivileged(Native Method)
at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393)
at sun.reflect.MethodAccessorGenerator.generateSerializationConstructor(MethodAccessorGenerator.java:112)
at sun.reflect.ReflectionFactory.generateConstructor(ReflectionFactory.java:398)
at sun.reflect.ReflectionFactory.newConstructorForSerialization(ReflectionFactory.java:360)
at java.io.ObjectStreamClass.getSerializableConstructor(ObjectStreamClass.java:1574)
at java.io.ObjectStreamClass.access$1500(ObjectStreamClass.java:79)
at java.io.ObjectStreamClass$3.run(ObjectStreamClass.java:519)
at java.io.ObjectStreamClass$3.run(ObjectStreamClass.java:494)
at java.security.AccessController.doPrivileged(Native Method)
at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:494)
at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:391)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1134)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at javax.management.remote.rmi.RMIConnectorServer.encodeJRMPStub(RMIConnectorServer.java:727)
at javax.management.remote.rmi.RMIConnectorServer.encodeStub(RMIConnectorServer.java:719)
at javax.management.remote.rmi.RMIConnectorServer.encodeStubInAddress(RMIConnectorServer.java:690)
at javax.management.remote.rmi.RMIConnectorServer.start(RMIConnectorServer.java:439)
at sun.management.jmxremote.ConnectorBootstrap.startLocalConnectorServer(ConnectorBootstrap.java:550)
at sun.management.Agent.startLocalManagementAgent(Agent.java:137)
複製代碼
直接內存溢出問題(少見) 《深刻理解Java虛擬機》P59,使用Unsafe分配直接內存,或者使用NIO的問題
棧溢出問題 -Xss設定過小
比較一下這兩段程序的異同,分析哪個是更優的寫法:
Object o = null;
for(int i=0; i<100; i++) {
o = new Object();
//業務處理
}複製代碼
for(int i=0; i<100; i++) {
Object o = new Object();
}複製代碼
重寫finalize引起頻繁GC 小米雲,HBase同步系統,系統經過nginx訪問超時報警,最後排查,C++程序員重寫finalize引起頻繁GC問題 爲何C++程序員會重寫finalize?(new delete) finalize耗時比較長(200ms)
若是有一個系統,內存一直消耗不超過10%,可是觀察GC日誌,發現FGC老是頻繁產生,會是什麼引發的? System.gc() (這個比較Low)
Distuptor有個能夠設置鏈的長度,若是過大,而後對象大,消費完不主動釋放,會溢出 (來自 死物風情)
用jvm都會溢出,mycat用崩過,1.6.5某個臨時版本解析sql子查詢算法有問題,9個exists的聯合sql就致使生成幾百萬的對象(來自 死物風情)
new 大量線程,會產生 native thread OOM,(low)應該用線程池, 解決方案:減小堆空間(太TMlow了),預留更多內存產生native thread JVM內存佔物理內存比例 50% - 80%
-XX:MaxTenuringThreshold控制的是什麼? A: 對象升入老年代的年齡 B: 老年代觸發FGC時的內存垃圾比例
生產環境中,傾向於將最大堆內存和最小堆內存設置爲:(爲何?) A: 相同 B:不一樣
JDK1.8默認的垃圾回收器是: A: ParNew + CMS B: G1 C: PS + ParallelOld D: 以上都不是
什麼是響應時間優先?
什麼是吞吐量優先?
ParNew和PS的區別是什麼?
ParNew和ParallelOld的區別是什麼?(年代不一樣,算法不一樣)
長時間計算的場景應該選擇:A:停頓時間 B: 吞吐量
大規模電商網站應該選擇:A:停頓時間 B: 吞吐量
HotSpot的垃圾收集器最經常使用有哪些?
常見的HotSpot垃圾收集器組合有哪些?
JDK1.7 1.8 1.9的默認垃圾回收器是什麼?如何查看?
所謂調優,究竟是在調什麼?
若是採用PS + ParrallelOld組合,怎麼作才能讓系統基本不產生FGC
若是採用ParNew + CMS組合,怎樣作纔可以讓系統基本不產生FGC
1.加大JVM內存
2.加大Young的比例
3.提升Y-O的年齡
4.提升S區比例
5.避免代碼內存泄漏
G1是否分代?G1垃圾回收器會產生FGC嗎?
若是G1產生FGC,你應該作什麼?
問:生產環境中可以隨隨便便的dump嗎? 小堆影響不大,大堆會有服務暫停或卡頓(加live能夠緩解),dump前會有FGC
問:常見的OOM問題有哪些? 棧 堆 MethodArea 直接內存