詳談jvm線程棧空間內存分配位置
jvm線程棧空間內存分配位置
jvm的線程棧申請的內存空間屬於堆外內存,是向操作系統申請的,也不是JVM直接內存,雖然類似。
JVM能創建的線程數需要的內存,不是JVM運行內存,堆內存,直接內存,而是操作系統剩餘的可用內存,這個也決定瞭能創建的線程數,如果內存不夠用,創建線程的時候便會出現內存溢出的錯誤。
在操作系統的可用內存不足的情況下,想要創建更多的線程,可以考慮減少線程棧的空間大小(-Xss),但是不建議過小,棧嘗試減小容易棧溢出錯誤。
————————–分割線————————–
後來有次早上5點睡不著,起床做瞭個測試驗證,在這裡補充下這個測試說明,當時隻是發瞭個朋友圈,過得有點久瞭現在我也隻從手機上找到幾張圖片貼上來:
JVM配置如下
設置最大堆10m,線程棧大小10m,直接內存5m。
創建1000條線程,調用10w次函數(調用次數再過多,棧深不夠就溢出瞭),瘋狂壓棧但不出棧(遞歸調用)。然後看內存,物理內存占用7g多,有次是5g多。沒有堆溢出,也沒有直接內存溢出。說明線程棧內存在堆外分配,不屬於堆內存(線程對象還是分配在堆內存空間),也不屬於直接內存部分。
測試截的一些圖片如下
JVM配置
main方法創建1條線程並運行:
main方法創建1000條線程並運行:
測試代碼
/** * @Auther: 許曉東 * @Date: 19-8-3 05:14 * @Description: */ public class ThreadStackTest { static Map<Integer, Thread> map = new HashMap<>(); static Runnable runnable = new Runnable() { @Override public void run() { try { recursive(1); } catch (InterruptedException e) { e.printStackTrace(); } } }; private static void recursive(int num) throws InterruptedException { if (num == 20000) { Thread.sleep(Integer.MAX_VALUE); }else { recursive(++num); } } public static void main(String[] args) throws InterruptedException { System.gc(); int nums = 1000; //int nums = 1; for (int i = 0; i < nums; i++) { map.put(i, new Thread(runnable)); } for (Thread thread : map.values()) { thread.start(); } System.out.println(String.format("創建%d條線程後gc情況:", nums)); System.gc(); Thread.sleep(Integer.MAX_VALUE); } }
jvm棧大小設置
1、棧內存大小設置
棧內存為線程私有的空間,每個線程都會創建私有的棧內存。棧空間內存設置過大,創建線程數量較多時會出現棧內存溢出StackOverflowError。同時,棧內存也決定方法調用的深度,棧內存過小則會導致方法調用的深度較小,如遞歸調用的次數較少。
-Xss:如-Xss128k
通常隻有幾百K
決定瞭函數調用的深度
每個線程都有獨立的棧空間
局部變量、參數 分配在棧上
2、遞歸調用
package com.thread.study; public class Stack { private static int count=0; public static void recursion(long a,long b,long c){ long e=1,f=2,g=3,h=4,i=5,k=6,q=7,x=8,y=9,z=10; count++; recursion(a,b,c); } public static void main(String args[]){ try{ recursion(0L,0L,0L); }catch(Throwable e){ System.out.println("deep of calling = "+count); e.printStackTrace(); } } }
- -Xss128k:deep of calling = 306
- -Xss256k:deep of calling = 761
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 一篇文章掌握Java Thread的類及其常見方法
- Java多線程Thread類的使用及註意事項
- Java Thread之Sleep()案例詳解
- 多線程如何解決for循環效率的問題
- Java多線程基礎