成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊Java中的內存溢出問題

開發 后端
內存溢出是指應用系統中存在無法回收的內存或使用的內存過多,最終使得程序運行要用到的內存大于虛擬機能提供的最大內存。這篇文章整理自《深入理解java虛擬機》。之前面阿里遇到過。

[[380301]]

內存溢出是指應用系統中存在無法回收的內存或使用的內存過多,最終使得程序運行要用到的內存大于虛擬機能提供的最大內存。這篇文章整理自《深入理解java虛擬機》。之前面阿里遇到過。

一、內存溢出原因

內存溢出就是內存不夠,引起內存溢出的原因有很多種,常見的有以下幾種:

1、內存中加載的數據量過于龐大,如一次從數據庫取出過多數據;

2、集合類中有對對象的引用,使用完后未清空,使得JVM不能回收;

3、代碼中存在死循環或循環產生過多重復的對象實體;

4、使用的第三方軟件中的BUG;

5、啟動參數內存值設定的過小;

當然實際情況中內存溢出的原因就太多了。下面我們就對這些原因分類一下:

以上的圖是基于java7來敘述的,從上面這張圖我們能夠得到如下信息:java虛擬機把內存分為5個模塊。

(1)程序計數器:程序計數器是線程私有的,主要的作用是通過改變這個計數器的值來選取下一條需要執行的字節碼指令。既然每個線程都有一個,那么這些線程的計數器是互不影響的。也不會拋出任何異常。

(2)虛擬機棧和本地方法棧:虛擬機棧描述的是java方法執行的內存模型,每個方法在執行的時候都會創建一個棧幀用于存儲局部變量表、操作數棧、動態連接、方法出口等信息。本地方法棧與虛擬機棧的區別是,虛擬機棧為虛擬機執行java方法服務,而本地方法棧則為虛擬機提供native方法服務。

在單線程的操作中,無論是由于棧幀太大,還是虛擬機棧空間太小,當棧空間無法分配時,虛擬機拋出的都是StackOverflowError異常,而不會得到OutOfMemoryError異常。而在多線程環境下,則會拋出OutOfMemoryError異常。

(3)java堆和方法區:java堆區主要存放對象實例和數組等,方法區保存類信息、常量、靜態變量等等。運行時常量池也是方法區的一部分。這兩塊區域是線程共享的區域,只會拋出OutOfMemoryError。

不知道各位在B站看見過那個面試經典場景沒,在回答java的內存運行數據區結構時,以上的功能作用是一方面,如果回答時把內存溢出問題添加上是一個極大的加分項。

二、內存溢出實例

1、堆溢出

既然堆是存放實例對象的,那我們就無線創建實例對象。這樣堆區遲早會滿。

  1. public class HeapOOM { 
  2.     static class User {} 
  3.  public static void main(String[] args) { 
  4.    List<User> list = new ArrayList<User>(); 
  5.          while (true) { 
  6.              list.add(new User()); 
  7.       } 
  8.  } 
  9. /*Exception in thread "main" java.lang.OutOfMemoryError:  
  10. GC overhead limit exceeded 
  11.  at com.fdd.test.HeapOOM.main(HeapOOM.java:11)*/ 

因為我提前設置了堆區內存,所以無限創建就會拋出異常。

2、虛擬機棧和本地方法棧溢出

Java虛擬機規范中描述了兩種異常:

如果線程請求的棧深度大于虛擬機鎖允許的最大深度,將拋出StackOverflowError異常。

如果虛擬機在擴展棧時無法申請到足夠的內存空間,則拋出OutOfMemoryError異常。

第一種我們只需要使用方法遞歸調用即可模擬:

  1. public class StackOutOfMemoryError { 
  2.     public static void main(String[] args) {      
  3.          test(); 
  4.     } 
  5.     private static void go() { 
  6.         System.out.println("StackOverflowError異常"); 
  7.         test(); 
  8.     } 
  9. /*Exception in thread "main" java.lang.StackOverflowError 
  10.  at sun.nio.cs.ext.DoubleByte$Encoder.encodeLoop(DoubleByte.java:617) 
  11.  at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579) 
  12.  at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271) 
  13.  at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125) 
  14.  at java.io.OutputStreamWriter.write(OutputStreamWriter.java:207) 
  15.  at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129) 
  16.  at java.io.PrintStream.write(PrintStream.java:526) 
  17.  at java.io.PrintStream.print(PrintStream.java:597) 
  18.  at java.io.PrintStream.println(PrintStream.java:736) 
  19.  at com.fdd.test.StackOutOfMemoryError.go(StackOutOfMemoryError.java:11) 
  20.  at com.fdd.test.StackOutOfMemoryError.go(StackOutOfMemoryError.java:13)*/ 

第二種也可以遞歸調用模擬,,但是使用的是類直接調用。

  1. public class JavaVMStackSOF { 
  2.     private int stackLength = 1; 
  3.     public void stackLeak() { 
  4.         stackLength++; 
  5.         stackLeak(); 
  6.     } 
  7.  public static void main(String[] args) { 
  8.         JavaVMStackSOF oom = new JavaVMStackSOF(); 
  9.         oom.stackLeak(); 
  10.     } 
  11. /*Exception in thread "main" java.lang.StackOverflowError 
  12.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:18) 
  13.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  14.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  15.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  16.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  17.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  18.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  19.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  20.    at com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:19) 
  21.    ... */ 

3、方法區和運行時常量池溢出

  1. public class JavaMethodAreaOOM { 
  2.     public static void main(String[] args) { 
  3.         while (true) { 
  4.             Enhancer enhancer = new Enhancer(); 
  5.             enhancer.setSuperclass(User.class); 
  6.             enhancer.setUseCache(false); 
  7.             enhancer.setCallback(new MethodInterceptor() { 
  8.                 public Object intercept(Object obj, Method method, 
  9.                       Object[] args, MethodProxy proxy) throws Throwable { 
  10.                     return proxy.invokeSuper(obj, args); 
  11.                 } 
  12.             }); 
  13.             enhancer.create(); 
  14.         } 
  15.     } 
  16.     static class User {} 
  17. /*Exception in thread "main" 
  18.  Exception: java.lang.OutOfMemoryError thrown  
  19.  from the UncaughtExceptionHandler in thread "main" 
  20. */ 

4、本機直接內存溢出

DirectMemory容量可通過-XX: MaxDirectMemorySize指定,如果不指定,則默認與Java堆最大值 (-Xmx指定)一樣。

  1. public class DirectMemoryOOM { 
  2.     private static final int _1MB = 1024 * 1024; 
  3.     public static void main(String[] args) throws Exception { 
  4.         Field unsafeField = Unsafe.class.getDeclaredFields()[0]; 
  5.         unsafeField.setAccessible(true); 
  6.         Unsafe unsafe = (Unsafe) unsafeField.get(null); 
  7.         while (true) { 
  8.             unsafe.allocateMemory(_1MB); 
  9.         } 
  10.     } 

上面介紹了幾個實例,那遇到這種問題如何排查呢?

三、內存溢出排查

排查其實最主要的就是檢查代碼,而且內存溢出往往都是代碼的問題。當然一下幾點都是需要注意的:

(1)內存中加載的數據量過于龐大,如一次從數據庫取出過多數據;

(2)集合類中有對對象的引用,使用完后未清空,使得JVM不能回收;

(3)代碼中存在死循環或循環產生過多重復的對象實體;

(4)使用的第三方軟件中的BUG;

(5)啟動參數內存值設定的過小;

最后就是解決了。

第一步,修改JVM啟動參數,直接增加內存。

第二步,檢查錯誤日志

第三步,對代碼進行走查和分析,找出可能發生內存溢出的位置。

一般情況下代碼出錯的概率會比較大一些,當然了不同的場景不同錯誤總是復雜多樣的。

本文轉載自微信公眾號「 愚公要移山」,可以通過以下二維碼關注。轉載本文請聯系 愚公要移山公眾號。

 

責任編輯:武曉燕 來源: 愚公要移山
相關推薦

2021-03-06 10:25:19

內存Java代碼

2010-09-26 15:53:25

JVM內存溢出

2023-08-29 11:38:27

Java內存

2024-04-25 10:06:03

內存泄漏

2022-03-25 09:01:16

CSS溢出屬性

2020-05-09 13:49:00

內存空間垃圾

2018-05-15 08:44:44

TensorFlowKeras內存

2021-12-24 10:17:54

Java數據時間戳

2024-01-31 10:11:41

Redis內存

2021-08-16 06:56:21

Slice數組類型內存

2012-03-14 10:58:27

Java

2011-08-25 10:50:32

SQL Server數Performance

2024-03-11 08:22:40

Java內存泄漏

2020-03-19 09:58:20

運維架構技術

2021-11-09 06:55:03

SQLServer排序

2012-01-12 11:02:00

云計算帶寬瓶頸

2015-03-30 11:18:50

內存管理Android

2013-06-26 16:14:26

Android加載圖片內存溢出

2012-05-15 02:04:22

JVMJava

2022-06-27 08:31:29

數據溢出無符號
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美一二三区 | 爱爱免费视频 | 婷婷综合久久 | 久久久久一区二区三区四区 | 中文字幕高清视频 | 国产性网 | 久久精品亚洲欧美日韩久久 | 中文字幕一区二区三区精彩视频 | 2018中文字幕第一页 | 久久亚洲国产精品日日av夜夜 | 剑来高清在线观看 | 欧美三区视频 | 成年人的视频免费观看 | 国产成人综合av | 久久亚洲一区二区三区四区 | 亚洲社区在线 | 国产一级电影网 | 色资源在线视频 | 一级做a爰片性色毛片 | 日本高清aⅴ毛片免费 | 伦理片97 | 成人免费黄视频 | 国产91在线视频 | 在线成人免费视频 | 一久久久 | 国产精品视频97 | 色欧美片视频在线观看 | 日韩精品免费在线观看 | 久久999 | 亚洲国产乱码 | 日韩av一区二区在线观看 | 一区二区在线看 | 国产精品久久久久久久久久久久久 | 欧美日韩国产一区二区三区 | 成人一区在线观看 | 欧美国产精品一区二区 | 黄色在线免费观看 | 国产亚洲精品成人av久久ww | 99热国产在线播放 | 国产精品美女久久久久久不卡 | 狠狠干av |