Thread 与虚拟机栈

x33g5p2x  于2022-02-11 转载在 其他  
字(3.6k)|赞(0)|评价(0)|浏览(178)

一 代码

package concurrent;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadCounter extends Thread {
    final static AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) {
        try {
            while (true) {
                new ThreadCounter().start();
            }
        } catch (Exception e) {
            System.out.println("failed at =>" + counter.get());
        }
    }

    @Override
    public void run() {
        try {
            System.out.println("The " + counter.getAndIncrement() + " thread be created.");
            TimeUnit.MINUTES.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

二 测试

测试脚本
E:\JVMDemo\demo2022\target\classes>java -Xmx512m -Xms64m concurrent.ThreadCounter

测试结果

The 114200 thread be created.
The 114199 thread be created.
Java HotSpot(TM) 64-Bit Server VM warning: The 114198 thread be created.Attempt to allocate stack guard pages failed.Java HotSpot(TM) 64-Bit Server VM warning:
Attempt to allocate stack guard pages failed.The 114197 thread be created.

The 114196 thread be created.
Java HotSpot(TM) 64-Bit Server VM warning: Java HotSpot(TM) 64-Bit Server VM warning:
The 114195 thread be created.Attempt to allocate stack guard pages failed.
Attempt to allocate stack guard pages failed.

The 114193 thread be created.Java HotSpot(TM) 64-Bit Server VM warning:
Attempt to allocate stack guard pages failed.#
The 114192 thread be created.
# A fatal error has been detected by the Java Runtime Environment:

The 114191 thread be created.#
Java HotSpot(TM) 64-Bit Server VM warning: Exception in thread "Thread-153048" #  [thread 631284 also had an error]Java HotSpot(TM) 64-Bit Server VM warning:
EXCEPTION_ACCESS_VIOLATIONAttempt to allocate stack guard pages failed.The 114190 thread be created.[thread 631264 also had an error]

The 114188 thread be created.

java.lang.StackOverflowError (0xc0000005)The 114187 thread be created.

        at java.lang.StringBuilder.append(StringBuilder.java:208)An unrecoverable stack overflow has occurred.The 114186 thread be created.
The 114185 thread be created. at pc=0x000000005d025127[thread 631228 also had an error] at concurrent.ThreadCounter.run(ThreadCounter.java:22)
The 114184 thread be created.
The 114183 thread be created.

三 默认情况下栈内存的大小

java -XX:+PrintFlagsFinal -version|find "ThreadStackSize"

四 Xms Xmx Xss 组合测试命令

java -Xmx512m -Xms64m -XX:ThreadStackSize=1m concurrent.ThreadCounter

五 栈内存变化导致线程数量的变化

| <br>Xms<br> | <br>Xmx<br> | <br>Xss<br> | <br>Threads<br> |
| <br>512m<br> | <br>512m<br> | <br>1m<br> | <br>63790<br> |
| <br>512m<br> | <br>512m<br> | <br>10m<br> | <br>60803<br> |
| <br>512m<br> | <br>512m<br> | <br>64m<br> | <br>32651<br> |
| <br>512m<br> | <br>512m<br> | <br>128m<br> | <br>20678<br> |
| <br>512m<br> | <br>512m<br> | <br>512m<br> | <br>6556<br> |

线程的创建数量是随着虚拟机栈内存的增大而减少。

六 堆空间变化导致线程数量的变化

| <br>Xms<br> | <br>Xmx<br> | <br>Xss<br> | <br>Threads<br> |
| <br>64m<br> | <br>64m<br> | <br>1m<br> | <br>92376<br> |
| <br>128m<br> | <br>128m<br> | <br>1m<br> | <br>90948<br> |
| <br>256m<br> | <br>256m<br> | <br>1m<br> | <br>90423<br> |
| <br>512m<br> | <br>512m<br> | <br>1m<br> | <br>87931<br> |
| <br>1024m<br> | <br>1024m<br> | <br>1m<br> | <br>83195<br> |

随着堆内存分配的增大,创建的线程数变小,只是没有像栈内存那样明显。

七 结论

虚拟机栈内存是线程私有的,也就是说每一个线程都会占有指定的内存大小,我们粗略地认为一个 Java的进程的内存大小为:堆空间 + 线程数量 * 栈内存。
线程数量 = (最大地址空间(MaxProcessMemory) - JVM堆内存 - ReservedOsMemory) /ThreadStackSize(XSS)

当然线程数量还与操作系统的一些内核配置有很大的关系。

八 参考

JVM高级运行时选项 Advanced Runtime Options - 知乎

相关文章