詳談jvm線程??臻g內(nèi)存分配位置
jvm線程??臻g內(nèi)存分配位置
jvm的線程棧申請的內(nèi)存空間屬于堆外內(nèi)存,是向操作系統(tǒng)申請的,也不是JVM直接內(nèi)存,雖然類似。
JVM能創(chuàng)建的線程數(shù)需要的內(nèi)存,不是JVM運(yùn)行內(nèi)存,堆內(nèi)存,直接內(nèi)存,而是操作系統(tǒng)剩余的可用內(nèi)存,這個也決定了能創(chuàng)建的線程數(shù),如果內(nèi)存不夠用,創(chuàng)建線程的時候便會出現(xiàn)內(nèi)存溢出的錯誤。
在操作系統(tǒng)的可用內(nèi)存不足的情況下,想要創(chuàng)建更多的線程,可以考慮減少線程棧的空間大?。?Xss),但是不建議過小,棧嘗試減小容易棧溢出錯誤。
--------------------------分割線--------------------------
后來有次早上5點(diǎn)睡不著,起床做了個測試驗(yàn)證,在這里補(bǔ)充下這個測試說明,當(dāng)時只是發(fā)了個朋友圈,過得有點(diǎn)久了現(xiàn)在我也只從手機(jī)上找到幾張圖片貼上來:
JVM配置如下
設(shè)置最大堆10m,線程棧大小10m,直接內(nèi)存5m。
創(chuàng)建1000條線程,調(diào)用10w次函數(shù)(調(diào)用次數(shù)再過多,棧深不夠就溢出了),瘋狂壓棧但不出棧(遞歸調(diào)用)。然后看內(nèi)存,物理內(nèi)存占用7g多,有次是5g多。沒有堆溢出,也沒有直接內(nèi)存溢出。說明線程棧內(nèi)存在堆外分配,不屬于堆內(nèi)存(線程對象還是分配在堆內(nèi)存空間),也不屬于直接內(nèi)存部分。
測試截的一些圖片如下
JVM配置
main方法創(chuàng)建1條線程并運(yùn)行:
main方法創(chuàng)建1000條線程并運(yùn)行:
測試代碼
/** * @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("創(chuàng)建%d條線程后gc情況:", nums)); System.gc(); Thread.sleep(Integer.MAX_VALUE); } }
jvm棧大小設(shè)置
1、棧內(nèi)存大小設(shè)置
棧內(nèi)存為線程私有的空間,每個線程都會創(chuàng)建私有的棧內(nèi)存。棧空間內(nèi)存設(shè)置過大,創(chuàng)建線程數(shù)量較多時會出現(xiàn)棧內(nèi)存溢出StackOverflowError。同時,棧內(nèi)存也決定方法調(diào)用的深度,棧內(nèi)存過小則會導(dǎo)致方法調(diào)用的深度較小,如遞歸調(diào)用的次數(shù)較少。
-Xss:如-Xss128k
通常只有幾百K
決定了函數(shù)調(diào)用的深度
每個線程都有獨(dú)立的棧空間
局部變量、參數(shù) 分配在棧上
2、遞歸調(diào)用
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
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
IntelliJ?IDEA2022.3?springboot?熱部署含靜態(tài)文件(最新推薦)
這篇文章主要介紹了IntelliJ?IDEA2022.3?springboot?熱部署含靜態(tài)文件,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01JAVA基本類型包裝類 BigDecimal BigInteger 的使用
Java 中預(yù)定義了八種基本數(shù)據(jù)類型,包括:byte,int,long,double,float,boolean,char,short,接下來文章小編將向大家介紹其中幾個類型的內(nèi)容,需要的朋友可以參考下文章2021-09-09JavaCV?本地視頻推流實(shí)現(xiàn)依賴示例
這篇文章主要為大家介紹了JavaCV?本地視頻推流實(shí)現(xiàn)的依賴示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08MyEclipse+Tomcat+MAVEN+SVN項目完整環(huán)境搭建(圖文教程)
這篇文章主要介紹了MyEclipse+Tomcat+MAVEN+SVN項目完整環(huán)境搭建(圖文教程),非常具有實(shí)用價值,需要的朋友可以參考下2017-12-12Java并發(fā)編程中的ReentrantLock類詳解
這篇文章主要介紹了Java并發(fā)編程中的ReentrantLock類詳解,ReentrantLock是juc.locks包中的一個獨(dú)占式可重入鎖,相比synchronized,它可以創(chuàng)建多個條件等待隊列,還支持公平/非公平鎖、可中斷、超時、輪詢等特性,需要的朋友可以參考下2023-12-12Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式
這篇文章主要介紹了Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09SpringBoot中的@CacheEvict 注解的實(shí)現(xiàn)
本文主要介紹了SpringBoot中的@CacheEvict注解的實(shí)現(xiàn),@CacheEvict 注解用于清空緩存,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03