java中的堆内存设置对线程创建数的影响以及-xss参数的记录

梦中彩虹      2022-04-27     413

关键词:

Java的线程对象是存储在堆上的,所以,能够创建多少个线程,受到堆空间的大小限制,同时也受到每个线程的大小的限制,假如线程对象内部有一个非常大的数组字段,那就非常影响能够创建的线程的大小

我们的例子:

class Task implements Runnable {
    //5M堆内存 128k的情况下,最多创建31个线程就挂了

    byte[] bytes = new byte[1024 * 128];

    @Override
    public void run() {
        while (true) {
            try {
                bytes[0] = 1;
                Thread.sleep(10_100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程对象内部持有一个数组字段,这个数组的大小是128k,我们的测试代码:

public static void threadTest3() {
        int count = 1;
        try {
            while (true) {

                Thread thread = new Thread(new Task());
                thread.start();
                System.out.println("==============================================" + count++);
            }
        } catch (Throwable e) {
            System.out.println(count);
            e.printStackTrace();
        }

    }

运行测试的时候,我们将堆的内存设置的小一些:

-Xmx5m -Xms5m XX:+PrintGC -XX:-PrintGCDetails

输出的日志如下:

"C:\Program Files\Java\jdk1.8.0_152\bin\java.exe" -Xmx5m -Xms5m -XX:+PrintGC -XX:-PrintGCDetails  com.jiaoyiping.baseproject.concurrent.ThreadTest
[GC (Allocation Failure)  1024K->732K(5632K), 0.0006644 secs]
[GC (Allocation Failure)  1746K->1023K(5632K), 0.0012964 secs]
[GC (Allocation Failure)  1818K->1417K(5632K), 0.0005073 secs]
[GC (Allocation Failure)  2441K->1546K(5632K), 0.0008099 secs]
[GC (Allocation Failure)  2570K->1773K(5632K), 0.0009678 secs]
==============================================1
[GC (Allocation Failure)  2752K->2046K(5632K), 0.0012278 secs]
==============================================2
==============================================3
==============================================4
==============================================5
==============================================6
==============================================7
==============================================8
[GC (Allocation Failure)  2962K->3022K(5632K), 0.0007815 secs]
==============================================9
==============================================10
==============================================11
==============================================12
==============================================13
==============================================14
==============================================15
[GC (Allocation Failure)  3938K->3950K(5632K), 0.0005197 secs]
[Full GC (Ergonomics)  3950K->3132K(5632K), 0.0098480 secs]
==============================================16
==============================================17
==============================================18
==============================================19
==============================================20
==============================================21
==============================================22
[GC (Allocation Failure)  4090K->4220K(5632K), 0.0004522 secs]
[Full GC (Ergonomics)  4220K->3975K(5632K), 0.0085720 secs]
==============================================23
==============================================24
==============================================25
==============================================26
==============================================27
==============================================28
==============================================29
[Full GC (Ergonomics)  4920K->4876K(5632K), 0.0110795 secs]
[Full GC (Allocation Failure)  4876K->4856K(5632K), 0.0086577 secs]
==============================================30
[Full GC (Ergonomics)  5015K->4985K(5632K), 0.0025122 secs]
[Full GC (Allocation Failure)  4985K->4985K(5632K), 0.0022044 secs]
31
java.lang.OutOfMemoryError: Java heap space
	at com.jiaoyiping.baseproject.concurrent.Task.<init>(ThreadTest.java:105)
	at com.jiaoyiping.baseproject.concurrent.ThreadTest.threadTest3(ThreadTest.java:74)
	at com.jiaoyiping.baseproject.concurrent.ThreadTest.main(ThreadTest.java:17)
[Full GC (Ergonomics)  5118K->4995K(5632K), 0.0108311 secs]
[Full GC (Ergonomics)  5107K->5029K(5632K), 0.0034520 secs]
[Full GC (Ergonomics)  5107K->5058K(5632K), 0.0034841 secs]
[Full GC (Ergonomics)  5107K->5064K(5632K), 0.0032645 secs]
[Full GC (Ergonomics)  5107K->5097K(5632K), 0.0034425 secs]
[Full GC (Ergonomics)  5107K->5107K(5632K), 0.0030512 secs]
[Full GC (Ergonomics)  5107K->5107K(5632K), 0.0027000 secs]
[Full GC (Ergonomics)  5109K->5109K(5632K), 0.0026329 secs]
[Full GC (Ergonomics)  5111K->5111K(5632K), 0.0026942 secs]
[Full GC (Ergonomics)  5113K->5113K(5632K), 0.0024612 secs]
[Full GC (Ergonomics)  5116K->5116K(5632K), 0.0028061 secs]
[Full GC (Ergonomics)  5118K->5118K(5632K), 0.0027730 secs]
[Full GC (Ergonomics)  5119K->5119K(5632K), 0.0039374 secs]
[Full GC (Allocation Failure)  5119K->5118K(5632K), 0.0037878 secs]
[Full GC (Ergonomics)  5119K->5119K(5632K), 0.0031486 secs]
[Full GC (Allocation Failure)  5119K->5119K(5632K), 0.0028138 secs]

当创建了30个线程的时候,就出现了堆内存的溢出

如果将bytes的值改变为56K呢,可以创建70个线程

-Xss影响的是栈的深度(比如栈的深度大的话,能够递归调用的次数就越多)
我们构造出来递归调用的例子,用来测试-Xss参数对递归调用的次数的影响

 public static void threadTest4() {
        try {
            add(0);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    static int add(int count) {
        System.out.println("invoke count" + (count + 1));
        return add(count + 1);
    }

当-Xss设置为128k的时候:

当-Xss设置为256K的时候:

jvm推荐的-Xss设置最少是108k,小于108K的时候,结果是不可预料的

5k-64k 无法创建虚拟机:

4k和以下很大的数值:

64K- 108K

这个值默认是1M我们一般不需要修改,值需要知道-Xss和栈的深度有关即可,通过以上的例子我们得到以下结论:堆内存的大小,和线程对象本身的大小,影响能够创建的线程的个数,-Xss影响栈的深度

除了Java虚拟机之外,操作系统也会对能创建多少个进程和线程进行限制

通过两个文件我们可以查看和修改这些限制数:
最大的PID
/proc/sys/kernel/threads-max

最多的线程数:
/proc/sys/kernel/pid_max

java堆栈内存分配

...个方法堆内存大小与堆内存相比非常少。三:Java程序中的堆和堆栈内存通过一个简单的程序来理解堆栈内存的使用情况/***Createdbyhuanjuluon12/10/17.*/publicclassHeapStackTestMemorypublicstaticvoidmain(String[]args)//Line1inti=1;//Line2Objectobj=n... 查看详情

windows编程中的堆管理(过于底层,一般不用关心)

摘要:本文主要对Windows内存管理中的堆管理技术进行讨论,并简要介绍了堆的创建、内存块的分配与再分配、堆的撤销以及new和delete操作符的使用等内容。  关键词:堆;堆管理  1引言  在大多数Windows应用程序设计中,... 查看详情

java中的堆内存和栈内存(代码片段)

...据了Java进程内存的大部分。栈内存栈内存用于存放程序中的基本数据类型变量和对象的引用变量,以及方法的调用和返回等数据。与堆内存相比,栈内存的开销较小,因此内存分配和回收速度也要快得多。栈上的内存存储只能... 查看详情

jvm内存区域(代码片段)

...程序计数器,多个线程之间互不影响。(可以理解为Java中的ThreadLoca 查看详情

java中的堆和栈以及堆栈的区别

... 2.栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外 查看详情

jvm中的堆和非堆内存(代码片段)

JVM内存包含以下部分:堆内存,它是Java对象的存储非堆内存,Java用于存储加载的类和其他元数据其他,JVM代码本身,JVM内部结构,加载的探查器代理代码和数据等。堆JVM有一个堆,它是运行时数据区,从中分配所有类实例和数... 查看详情

与 Java 中的 volatile 字段和同步块的关系发生在之前 - 以及它们对非易失性变量的影响?

】与Java中的volatile字段和同步块的关系发生在之前-以及它们对非易失性变量的影响?【英文标题】:Happens-beforerelationshipswithvolatilefieldsandsynchronizedblocksinJava-andtheirimpactonnon-volatilevariables?【发布时间】:2013-06-1102:32:47【问题描述... 查看详情

java如何依据cpu核数设置合适的线程数

...ewFixedThreadPool(nThreads);//nThreads为线程数2:这个只要服务器内存够大,CPU核心数较多,处理数据比较强就好了,注意不要一下分配几千个线程,可能会导致堆栈溢出的,这样程序就挂了,因为线程很费内存资源追问谢谢你的回答。... 查看详情

(转)举例讲解java中的堆和栈

转自:http://blog.csdn.net/lifuxiangcaohui/article/details/24936839 Java中堆和堆栈的区别   1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。(降低内存或... 查看详情

两个或多个线程如何在它们分配的堆上共享内存?

】两个或多个线程如何在它们分配的堆上共享内存?【英文标题】:Howdotwoormorethreadssharememoryontheheapthattheyhaveallocated?【发布时间】:2012-08-0804:52:53【问题描述】:正如标题所说,两个或多个线程如何共享它们分配的堆上的内存?... 查看详情

java中的堆内存与栈内存,你get到了吗?

Java中的堆和栈学Java的朋友应该都知道,在Java中把「内存」划分成两种:一种是「栈内存」,一种是「堆内存」。我们平时在函数中定义的一些「基本类型的变量」和「对象的引用变量」都是在函数的「栈内存」中分配的。当我... 查看详情

jvmiz9是什么意思

...的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,... 查看详情

java堆栈内存分配

...和栈内存的教程以及参考说明,但是很难解释什么是程序的堆内存以及栈内存一:Java堆内存空间Java程序运行时使用javaHeap内存为对象以及JRE类分配内存,不论我们在何时创建何种类型的对象,他总是在堆内存中创建的Java垃圾收... 查看详情

如何对元素多于每个块的线程数的数组执行并行扫描?

...管我看到的所有实现都在共享内存中工作,但内存只在块中的线程之间共享。是否 查看详情

java - 如何在java中的堆上单独获取所有对象消耗的运行时内存

】java-如何在java中的堆上单独获取所有对象消耗的运行时内存【英文标题】:Howtogetruntimememoryconsumedbyalltheobjectsindividuallyonheapinjava【发布时间】:2013-08-1607:16:44【问题描述】:我目前正在运行以下代码,这表明我的java应用程序正... 查看详情

十分钟吃透java内存模型(代码片段)

...执行同样的代码,这两个线程任然在在自己的线程栈中的代码来创建 查看详情

Java中的数组以及它们如何存储在内存中

】Java中的数组以及它们如何存储在内存中【英文标题】:ArraysinJavaandhowtheyarestoredinmemory【发布时间】:2011-07-3016:22:45【问题描述】:我正在尝试了解java中的数组设置。为什么必须在创建数组后为数组中的每个对象初始化空间。... 查看详情

java常用四大线程池用法以及threadpoolexecutor详解(代码片段)

...是Executor这个接口,具体实现为ThreadPoolExecutor类,学习Java中的线程池,就可以直接学习他了对线程池的配置,就是对ThreadPoolExecutor构造函数的参数的配置 查看详情