詳談jvm線程??臻g內(nèi)存分配位置
jvm線程??臻g內(nèi)存分配位置
jvm的線程棧申請(qǐng)的內(nèi)存空間屬于堆外內(nèi)存,是向操作系統(tǒng)申請(qǐng)的,也不是JVM直接內(nèi)存,雖然類似。
JVM能創(chuàng)建的線程數(shù)需要的內(nèi)存,不是JVM運(yùn)行內(nèi)存,堆內(nèi)存,直接內(nèi)存,而是操作系統(tǒng)剩余的可用內(nèi)存,這個(gè)也決定了能創(chuàng)建的線程數(shù),如果內(nèi)存不夠用,創(chuàng)建線程的時(shí)候便會(huì)出現(xiàn)內(nèi)存溢出的錯(cuò)誤。
在操作系統(tǒng)的可用內(nèi)存不足的情況下,想要?jiǎng)?chuàng)建更多的線程,可以考慮減少線程棧的空間大?。?Xss),但是不建議過(guò)小,棧嘗試減小容易棧溢出錯(cuò)誤。
--------------------------分割線--------------------------
后來(lái)有次早上5點(diǎn)睡不著,起床做了個(gè)測(cè)試驗(yàn)證,在這里補(bǔ)充下這個(gè)測(cè)試說(shuō)明,當(dāng)時(shí)只是發(fā)了個(gè)朋友圈,過(guò)得有點(diǎn)久了現(xiàn)在我也只從手機(jī)上找到幾張圖片貼上來(lái):
JVM配置如下
設(shè)置最大堆10m,線程棧大小10m,直接內(nèi)存5m。
創(chuàng)建1000條線程,調(diào)用10w次函數(shù)(調(diào)用次數(shù)再過(guò)多,棧深不夠就溢出了),瘋狂壓棧但不出棧(遞歸調(diào)用)。然后看內(nèi)存,物理內(nèi)存占用7g多,有次是5g多。沒(méi)有堆溢出,也沒(méi)有直接內(nèi)存溢出。說(shuō)明線程棧內(nèi)存在堆外分配,不屬于堆內(nèi)存(線程對(duì)象還是分配在堆內(nèi)存空間),也不屬于直接內(nèi)存部分。
測(cè)試截的一些圖片如下
JVM配置

main方法創(chuàng)建1條線程并運(yùn)行:

main方法創(chuàng)建1000條線程并運(yùn)行:

測(cè)試代碼
/**
* @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)存為線程私有的空間,每個(gè)線程都會(huì)創(chuàng)建私有的棧內(nèi)存。??臻g內(nèi)存設(shè)置過(guò)大,創(chuàng)建線程數(shù)量較多時(shí)會(huì)出現(xiàn)棧內(nèi)存溢出StackOverflowError。同時(shí),棧內(nèi)存也決定方法調(diào)用的深度,棧內(nèi)存過(guò)小則會(huì)導(dǎo)致方法調(diào)用的深度較小,如遞歸調(diào)用的次數(shù)較少。
-Xss:如-Xss128k
通常只有幾百K
決定了函數(shù)調(diào)用的深度
每個(gè)線程都有獨(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
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
idea運(yùn)行main方法或Test避免編譯整個(gè)應(yīng)用的實(shí)現(xiàn)方法
這篇文章主要介紹了idea運(yùn)行main方法或Test避免編譯整個(gè)應(yīng)用的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
JavaWeb Session 會(huì)話管理實(shí)例詳解
這篇文章主要介紹了JavaWeb Session 會(huì)話管理的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-09-09
Java導(dǎo)入新項(xiàng)目報(bào)錯(cuò)java:JDK?isn‘t?specified?for?module解決辦法
這篇文章主要給大家介紹了關(guān)于Java導(dǎo)入新項(xiàng)目報(bào)錯(cuò)java:JDK?isn‘t?specified?for?module的解決辦法,當(dāng)您在導(dǎo)入Java項(xiàng)目時(shí)遇到錯(cuò)誤時(shí),可以嘗試以下面的方法來(lái)處理,需要的朋友可以參考下2024-05-05
為什么在重寫 equals方法的同時(shí)必須重寫 hashcode方法
Object 類是所有類的父類,其 equals 方法比較的是兩個(gè)對(duì)象的引用指向的地址,hashcode 是一個(gè)本地方法,返回的是對(duì)象地址值。他們都是通過(guò)比較地址來(lái)比較對(duì)象是否相等的2016-07-07
Java實(shí)現(xiàn)解析第三方接口返回的json
在實(shí)際開發(fā)過(guò)程中,免不了和其他公司進(jìn)行聯(lián)調(diào),調(diào)用第三方接口,這個(gè)時(shí)候我們就需要根據(jù)對(duì)方返回的數(shù)據(jù)進(jìn)行解析,獲得我們想要的字段,下面我們就來(lái)看看具體有哪些方法吧2024-01-01
關(guān)于@Transactional事務(wù)表被鎖的問(wèn)題及解決
這篇文章主要介紹了關(guān)于@Transactional事務(wù)表被鎖的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
使用idea搭建一個(gè)spring mvc項(xiàng)目的圖文教程
這篇文章主要介紹了使用idea直接創(chuàng)建一個(gè)spring mvc項(xiàng)目的圖文教程,本文通過(guò)圖文并茂的方式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03

