Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 热点堆栈保护页。红色/黄色区域及其背后的原因_Java_Jvm_Jvm Hotspot - Fatal编程技术网

Java 热点堆栈保护页。红色/黄色区域及其背后的原因

Java 热点堆栈保护页。红色/黄色区域及其背后的原因,java,jvm,jvm-hotspot,Java,Jvm,Jvm Hotspot,Java线程堆栈组织如下所述。因此,1 glibc保护页似乎是默认值,由pthread\u attr\u init(pthread\u attr*)设置 我可以想象在红色/黄色区域后面的原因是在不接收SIGSEGV的情况下处理堆栈溢出。此外,此处的红色区域明确表示与中指定的内容不同的内容,其中设置为rsp下方的128字节,并表示中断/信号处理程序不会触及它 热点红色区域由-XX:StackRedPages选项控制,据我所知,它的大小可能是0到3页 我还发现,当原始线程创建一个执行初始化步骤的线程

Java线程堆栈组织如下所述。因此,1 glibc保护页似乎是默认值,由
pthread\u attr\u init(pthread\u attr*)
设置

我可以想象在红色/黄色区域后面的原因是在不接收
SIGSEGV
的情况下处理堆栈溢出。此外,此处的红色区域明确表示与中指定的内容不同的内容,其中设置为rsp下方的128字节,并表示中断/信号处理程序不会触及它

热点红色区域由
-XX:StackRedPages
选项控制,据我所知,它的大小可能是
0
3

我还发现,当原始线程创建一个执行初始化步骤的线程时,它会执行初始化步骤

Q:红色/黄色区域是用来做什么的,为什么执行初始化的线程是在没有
pthread
保护页的情况下创建的?

在Linux上,红色和黄色保留区域的用法是使JVM热点处理堆栈溢出
pthreads\u attr\u setguardsize
手册页有一条关于将保护大小设置为0的注释:

应用程序负责处理堆栈溢出 (可能通过使用
mprotect(2)
在 已分配的堆栈的末尾)

将保护大小设置为0可能有助于节省存储空间中的内存 创建多个线程并知道堆栈溢出的应用程序 永远不会发生

因此,由于没有线程(即使是原始线程)对其堆栈使用
MAP\u GROWSDOWN
映射,因此在这种情况下,将保护大小设置为0可能被视为一种优化。JVM在函数中手动映射的
保留
/
黄色
/
红色
页面保证了“不会发生堆栈溢出”

可以看出,线程堆栈底部的某些部分,即使没有
pthread
的保护页,也会被视为
mprotect
的保护页,正如手册页面告诉我们的那样

堆栈溢出的实际处理是通过JVM启动时安装的。与堆栈溢出相关的部分如下(有点长):

从代码中可以看出。如果在保留区或黄色区域上未防护保护页时引发
SIGSEGV
,则
StackOverflowerError
错误被调度到Java中,并且在堆栈展开时重新启用防护

相反,如果在红色区域中引发
SIGSEGV
,则将其视为“不可恢复的堆栈溢出错误”

例如:

public class Main {
    static void foo() throws Exception {
        foo();
    }

    public static void main(String args[]) throws Exception {
        foo();
    }
}
通过
gdb
可以注意到,此
堆栈溢出错误发生在保留/黄色区域,而不是红色区域(因此这可能是
try
-
catch
处理程序可以处理此错误的原因)


作为结论,热点保护红色区域的含义与红色区域定义完全不同(只是调用方可以放置本地变量的区域,这样它们就不会被信号/中断处理程序或调试器触及,因为
gdb
可能会将自己的数据放在红色区域之外的堆栈上)

见@apangin。看起来很有趣。
public class Main {
    static void foo() throws Exception {
        foo();
    }

    public static void main(String args[]) throws Exception {
        foo();
    }
}