摘要:內存模型先聊聊內存模型,在網上找到一張有直接內存的圖片,方便后面討論這張圖真是??闯P?,今天我們從內存溢出的角度重新再審視一遍。
JVM內存模型
先聊聊jvm內存模型,在網上找到一張有直接內存的圖片,方便后面討論
這張圖真是常看常新,今天我們從內存溢出的角度重新再審視一遍。
方法區,也稱非堆,hotspot中,1.7叫perm區,1.8叫元空間,因此這個區域溢出,1.7就是OutOfMemoryError: PermGen space,1.8是OutOfMemoryError: Metaspace
堆溢出比較常見,OutOfMemoryError: Java heap space
虛擬機棧的溢出是 StackOverflowError
本地方法棧會出現 java.lang.OutOfMemoryError : unable to create new native Thread
直接內存會拋出 OutOfMemoryError: Direct buffer memory
以下將逐個撐爆這些空間
先來撐爆虛擬機棧 StackOverflowError不停地遞歸調用,jvm不得不在虛擬機棧上分配棧幀空間,從而導致sofe,感興趣的還可以查看一下遞歸的次數,可能通過-Xss進行配置,通過命令jinfo -flag ThreadStackSize [pid]可以查看棧空間大小的配置
public class StackOverflowErrorDemo { private static void test() { test(); } public static void main(String[] args) { test(); } }再來撐爆堆吧 OutOfMemoryError: Java heap space
先指定-Xmx8m -Xms8m,然后直接在堆中生成一個8m字節的數組,可以直接看到效果
public class JavaHeapSpaceDemo { public static void main(String[] args) { byte[] bytes = new byte[8 * 1014 * 1024]; } }
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space方法區有分說
at com.meituan.waimai.jvm.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:11)
如果是1.7,會出現PemGen space, 這要求我們不斷往生成類的信息。由于1.7,字符串常量池已經挪到堆中了,所以使用String.intern()并不會導致perm區溢出
public class OOMDemo { public static void main(String[] args) { String str = "hello"; Listlist = Lists.newArrayList(); for (int i = 0; i < Integer.MAX_VALUE; i++) { str += (i + "").intern(); list.add(str); } } }
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at com.meituan.waimai.jvm.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:18)
那要怎么做呢,這里我們需要動態地生成一些類,直到把perm區撐爆,jvm參數配置:-XX:MaxPermSize=8m
static class OOMTest{} public static void main(final String[] args) { int i = 0; try { for (; ; ) { i++; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(OOMTest.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o, args); } }); enhancer.create(); } } catch (Throwable throwable) { throwable.printStackTrace(); } } }
Caused by: java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
... 8 more
將jdk改為1.8,-XX:MaxMetaspaceSize=20m 重新執行上述程序,結果變成Metaspace溢出
java.lang.OutOfMemoryError: Metaspace該對直接內存動手的
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:114)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
at com.meituan.waimai.jvm.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:36)
配置jvm參數,-XX:MaxDirectMemorySize=8m,然后分配9m的直接內存:
public class DirectMemoryDemo { public static void main(String[] args) { ByteBuffer byteBuffer = ByteBuffer.allocateDirect(9 * 1024 * 1024); } }
可以看到
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory本地方法棧 unable to create new native Thread
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at com.meituan.waimai.jvm.DirectMemoryDemo.main(DirectMemoryDemo.java:13)
不停地創建java線程,就可以把本地方法棧撐爆
public class NativeThreadDemo { public static void main(String[] args) { for (; ; ) { new Thread(()->{ try { TimeUnit.SECONDS.sleep(Integer.MAX_VALUE); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } } }
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at com.meituan.waimai.jvm.NativeThreadDemo.main(NativeThreadDemo.java:21)
這個程序跑完忘了關,結果一會mac重啟了,非??膳隆?。。。
關于unable to create new native Thread,知乎上有個非常深刻地討論
https://www.zhihu.com/questio...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/76036.html
摘要:加載圖的機制是什么,為何不會內存泄漏自定義可拖動的顯示高清大圖的技術博客大總結提供一個設置圖片的入口,里面去獲得圖片的真實的寬度和高度,以及初始化我們的重寫,在里面根據用戶移動的手勢,去更新顯示區域的參數。 目錄介紹 7.0.0.1 加載bitmap圖片的時候需要注意什么?為何bitmap容易造成OOM?如何計算Bitmap占用內存? 7.0.0.2 如何理解recycle釋放內存問...
摘要:和的區別來自類,和來自類調用方法的過程中,線程不會釋放對象鎖。機制在使用迭代器的過程中有其他線程修改了,那么將拋出,這就是所謂機制。 面試是我們每個人都要經歷的事情,大部分人且不止一次,這里給大家總結最新的2016年面試題,讓大家在找工作時候能夠事半功倍。 1 Switch能否用string做參數? a.在 Java 7 之前, switch 只能支持byte,short,char,i...
摘要:線程掛起,線程繼續走,還會被繼續使用方法,而這時用的是線程設置的值了,而這就是引發問題的根源,出現時間不對,線程掛死等等。建議為每個線程創建單獨的格式實例。其中工作隊列使用的是,源碼頭部的注釋中有說明截取的部分。 閱讀本文大概需要 3.2 分鐘。 前言 日常開發中,我們經常需要使用時間相關類,想必大家對SimpleDateFormat并不陌生。主要是用它進行時間的格式化輸出和解析,...
摘要:我知道最近世麟心情是錯綜復雜,但還好的是絕大多數程序員都是特別有善心的。如果圖像數據較大就會造成對象申請的內存較多,如果圖像過多就會造成內存不夠用自然就會出現的現象。第二次將設置為再次調用函數時就能生成了。 目錄介紹 01.先看一個需求分析案例 02.Bitmap占用內存介紹 03.影響Bitmap占用內存因素 04.圖像加載的方式 05.加載圖像內存去哪里了 06.具體實現加載圖片...
閱讀 2675·2021-11-25 09:43
閱讀 2587·2021-11-22 09:34
閱讀 2856·2021-11-12 10:34
閱讀 1442·2021-10-20 13:46
閱讀 2307·2019-08-30 13:21
閱讀 935·2019-08-30 11:21
閱讀 488·2019-08-30 11:20
閱讀 2192·2019-08-29 17:20