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

關于內存安全問題,你應該了解的幾點!

存儲 存儲軟件
Java在內存管理方面是要比C/C++更方便的,不需要為每一個對象編寫釋放內存的代碼,JVM虛擬機將為我們選擇合適的時間釋放內存空間,使得程序不容易出現內存泄漏和溢出的問題

[[394720]]

前言

Java在內存管理方面是要比C/C++更方便的,不需要為每一個對象編寫釋放內存的代碼,JVM虛擬機將為我們選擇合適的時間釋放內存空間,使得程序不容易出現內存泄漏和溢出的問題

不過,也正是因為Java把內存控制的權利交給了Java虛擬機,一旦出現內存泄漏和溢出方面的問題,如果不了解虛擬機是怎么使用內存的,那排查錯誤將會成為一項異常艱難的工作

下面先看看JVM如何管理內存的

內存管理

根據Java虛擬機規范(第3版) 的規定,Java虛擬機所管理的內存將會包括以下幾個運行內存數據區域:

  • 線程隔離數據區:
    • 程序計數器: 當前線程所執行字節碼的行號指示器
    • 虛擬機棧: 里面的元素叫棧幀,存儲局部變量表、操作棧、動態鏈接、方法出口等,方法被調用到執行完成的過程對應一個棧幀在虛擬機棧中入棧到出棧的過程。
    • 本地方法棧: 和虛擬機棧的區別在于虛擬機棧為虛擬機執行Java方法,本地方法棧為虛擬機使用到的本地Native方法服務。
  • 線程共享數據區:
    • 方法區: 可以描述為堆的一個邏輯部分,或者說使用永久代來實現方法區。存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。
    • 堆: 唯一目的就是存放對象的實例,是垃圾回收管理器的主要區域,分為Eden、From/To Survivor空間。

Java各版本內存管理改進

下圖中永久代理解為堆的邏輯區域,移除永久代的工作從JDK7就已經開始了,部分永久代中的數據(常量池)在JDK7中就已經轉移到了堆中,JDK8中直接去除了永久代,方法區中的數據大部分被移到堆里面,還剩下一些元數據被保存在元空間里

內存溢出

  • 內存泄露Memory Leak: 申請的內存空間沒有及時釋放,導致后續程序里這塊內容永遠被占用。
  • 內存溢出Out Of Memory: 要求的內存超過了系統所能提供的

運行時數據區域的常見異常

在JVM中,除了程序計數器外,虛擬機內存的其他幾個運行時數據區域都有發生OOM異常的可能。

堆內存溢出

不斷的創建對象,并且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象。

  1. public class HeapOOM { 
  2.     static class ObjectInHeap{ 
  3.     } 
  4.     public static void main(String[] args) { 
  5.         List<ObjectInHeap> list = new ArrayList(); 
  6.         while (true) { 
  7.             list.add(new ObjectInHeap()); 
  8.         } 
  9.     } 

棧溢出

單個線程下不斷擴大棧的深度引起棧溢出。

  1. public class StackSOF { 
  2.     private int stackLength = 1; 
  3.     public void stackLeak() { 
  4.         stackLength++; 
  5.         stackLeak(); 
  6.     } 
  7.     public static void main(String[] args) { 
  8.         StackSOF sof = new StackSOF(); 
  9.         try { 
  10.             sof.stackLeak(); 
  11.         } catch (Throwable e) { 
  12.             System.out.println("Stack Length: " + sof.stackLength); 
  13.             throw e; 
  14.         } 
  15.     } 

循環的創建線程,達到最大棧容量。

  1. public class StackOOM { 
  2.     private void dontStop() { 
  3.         while (true) { 
  4.         } 
  5.     } 
  6.     public void stackLeadByThread() { 
  7.         while (true) { 
  8.             Thread thread = new Thread(new Runnable() { 
  9.                 @Override 
  10.                 public void run() { 
  11.                     dontStop(); 
  12.                 } 
  13.             }); 
  14.             thread.start(); 
  15.         } 
  16.     } 
  17.     public static void main(String[] args) { 
  18.         StackOOM stackOOM = new StackOOM(); 
  19.         stackOOM.stackLeadByThread(); 
  20.     } 

運行時常量池溢出

不斷的在常量池中新建String,并且保持引用不釋放。

  1. public class RuntimeConstantPoolOOM { 
  2.     public static void main(String[] args) { 
  3.         // 使用List保持著常量池的引用,避免Full GC回收常量池 
  4.         List<String> list = new ArrayList<String>(); 
  5.         int i = 0; 
  6.         while (true) { 
  7.             // intern()方法使String放入常量池 
  8.             list.add(String.valueOf(i++).intern()); 
  9.         } 
  10.     } 

方法區溢出

借助CGLib直接操作字節碼運行時產生大量的動態類,最終撐爆內存導致方法區溢出。

  1. public class MethodAreaOOM { 
  2.     static class ObjectInMethod { 
  3.     } 
  4.     public static void main(final String[] args) { 
  5.         // 借助CGLib實現 
  6.         while (true) { 
  7.             Enhancer enhancer = new Enhancer(); 
  8.             enhancer.setSuperclass(ObjectInMethod.class); 
  9.             enhancer.setUseCache(false); 
  10.             enhancer.setCallback(new MethodInterceptor() { 
  11.                 @Override 
  12.                 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 
  13.                     return methodProxy.invokeSuper(o, objects); 
  14.                 } 
  15.             }); 
  16.             enhancer.create(); 
  17.         } 
  18.     } 

元空間溢出

助CG Lib運行時產生大量動態類,唯一的區別在于運行環境修改為Java 1.8,設置-XX:MaxMetaspaceSize參數,便可以收獲java.lang.OutOfMemoryError: Metaspace這一報錯

本機直接內存溢出

直接申請分配內存(實際上并沒有真正向操作系統申請分配內存,而是通過計算得知內存無法分配,于是拋出異常)

  1. public class DirectMemoryOOM { 
  2.     private static final int _1MB = 1024 * 1024; 
  3.     public static void main(String[] args) throws IllegalAccessException { 
  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.     } 

常見案例

在工作中一般會遇到有以下幾種情況導致內存問題

傳輸數據量過大

因為傳輸數量過大、或一些極端情況導致代碼中間結果對象數據量過大,過大的數據量撐爆內存

查詢出大量對象

這個多為SQL語句設置問題,SQL未設置分頁,用戶一次查詢數據量過大、頻繁查詢SQL導致內存堆積、或是未作判空處理導致WHERE條件為空查詢出超大數據量等

接口性能問題導致

這類為外部接口性能較慢,占用內存較大,并且短時間內高QPS導致的,導致服務內存不足,線程堆積或掛起進而出現FullGC

元空間問題

使用了大量的反射代碼,Java字節碼存取器生成的類不斷生成

問題排查

使用jmap分析內存泄漏

1.生成dump文件

  1. jmap -dump:format=b,file=/xx/xx/xx.hprof pid 

2.dump文件下載到本地

3.dump文件分析

可以使用MAT,MAT可作為Eclipse插件或一個獨立軟件使用,MAT是一個高性能、具備豐富功能的Java堆內存分析工具,主要用來排查內存泄漏和內存浪費的問題。

使用MAT打開上一部后綴名.hprof的dump文件

  • Histogram:直方圖,各個類的實例,包括個數和大小,可以查看類引用和被引用的路徑。
  • Dominator Tree:支配圖,列出所有線程和線程下面的那些對象占用的空間。
  • Top Consumers:通過圖形列出消耗內存多的實例。
  • Leak Suspects:MAT自動分析的內存泄漏報表

可以用這個工具分析出什么對象什么線程占用內存空間較大,對象是被什么引用的,線程內有哪些資源占用很高

以運行時常量池溢出為例

打開Histogram類實例表

Objects是類的對象的數量;Shallow是對象本身占用內存大小、不包含其他引用;

Retained是對象自己的Shallow加上直接或間接訪問到對象的Shallow之和,也可以說是GC之后可以回收的內存總和

從圖中可以看出運行時常量池溢出的情況,產生了大量的String和char[]實例

在char[]上右鍵可以得到上圖所有char[]對象的被引用路徑,可以看出這些char數組都是以String的形式存在ArrayList中,并且是由main這個線程運行的

可以看出是main線程中新建了一個數組,其中存了32w+個長度為6的char數組組成的String造成的內存溢出

 

關于MAT的詳細使用可以從MAT官方教程學習更多

 

責任編輯:武曉燕 來源: 月伴飛魚
相關推薦

2020-10-29 10:26:28

DevOps軟件自動化

2024-09-02 14:24:13

2020-04-28 18:20:04

Ubuntu 20.0UbuntuLinux

2024-02-21 23:11:19

2023-09-02 21:31:16

Java內存泄漏

2012-01-16 10:41:25

安全互聯網IT部門

2011-03-29 10:41:51

Java線程安全

2011-07-14 14:21:11

2024-07-30 13:48:37

2018-08-23 08:21:54

TensorFlow機器學習人工智能

2018-06-11 11:03:09

2020-02-27 09:39:42

云安全云計算網絡安全

2015-03-20 09:22:01

網絡安全授權用戶身份訪問管理

2019-02-13 15:49:00

2011-07-18 08:58:24

2013-09-17 09:35:15

云存儲

2020-11-15 23:29:01

大數據安全數據安全網絡攻擊

2012-11-20 10:47:16

2018-03-22 16:32:49

大數據數據集數據處理

2013-09-30 09:18:39

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人片免费看 | 欧美嘿咻 | 国产高清一区二区三区 | h免费观看| 久久久久久综合 | 特级黄一级播放 | 久草青青草| 欧美成人a∨高清免费观看 色999日韩 | 精品亚洲一区二区 | 国产乱肥老妇国产一区二 | 涩在线| 成人国产精品入口免费视频 | 精品国产一区二区国模嫣然 | 成人av在线网站 | 夜夜摸夜夜操 | 亚洲日本欧美 | www.久草.com| 91精品久久久久久久久久 | 亚洲精选一区二区 | 国产精品不卡一区 | 亚洲成人精品免费 | 日日噜噜噜夜夜爽爽狠狠视频, | 久久在线 | 久久久久久免费精品一区二区三区 | 亚州综合一区 | 欧美一区二区三区在线看 | 性欧美精品一区二区三区在线播放 | 欧美日韩在线观看视频网站 | 一级女毛片 | 成人免费xxxxx在线视频 | 欧美成人影院 | 亚洲免费精品 | 成人h电影在线观看 | 黄色av一区 | 国产一区亚洲 | 黄色片网站在线观看 | 欧美精品一区二区三区一线天视频 | 免费视频一区二区 | 综合久久一区 | 成人久久18免费网站图片 | 久草成人|