詳談jvm線程棧空間內(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)睡不著,起床做了個測試驗證,在這里補(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ú)立的??臻g
局部變量、參數(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)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
IntelliJ?IDEA2022.3?springboot?熱部署含靜態(tài)文件(最新推薦)
這篇文章主要介紹了IntelliJ?IDEA2022.3?springboot?熱部署含靜態(tài)文件,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01
JAVA基本類型包裝類 BigDecimal BigInteger 的使用
Java 中預(yù)定義了八種基本數(shù)據(jù)類型,包括:byte,int,long,double,float,boolean,char,short,接下來文章小編將向大家介紹其中幾個類型的內(nèi)容,需要的朋友可以參考下文章2021-09-09
JavaCV?本地視頻推流實(shí)現(xiàn)依賴示例
這篇文章主要為大家介紹了JavaCV?本地視頻推流實(shí)現(xiàn)的依賴示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
MyEclipse+Tomcat+MAVEN+SVN項目完整環(huán)境搭建(圖文教程)
這篇文章主要介紹了MyEclipse+Tomcat+MAVEN+SVN項目完整環(huán)境搭建(圖文教程),非常具有實(shí)用價值,需要的朋友可以參考下2017-12-12
Java并發(fā)編程中的ReentrantLock類詳解
這篇文章主要介紹了Java并發(fā)編程中的ReentrantLock類詳解,ReentrantLock是juc.locks包中的一個獨(dú)占式可重入鎖,相比synchronized,它可以創(chuàng)建多個條件等待隊列,還支持公平/非公平鎖、可中斷、超時、輪詢等特性,需要的朋友可以參考下2023-12-12
Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式
這篇文章主要介紹了Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
SpringBoot中的@CacheEvict 注解的實(shí)現(xiàn)
本文主要介紹了SpringBoot中的@CacheEvict注解的實(shí)現(xiàn),@CacheEvict 注解用于清空緩存,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03

