这发生在Linux2.6.18-238.5.1.el5和64位应用程序上。我的进程堆栈大小是10 My。但是,在对JNI_CreateJavaVM进行(成功)调用后,堆栈上似乎只剩下1-2 MB。如果我通过它-我的记忆错误,好像我是溢出堆栈。
几个注意事项:
测试来源:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
void CreateVM(JavaVM ** jvm) {
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = (char*)"-Xcheck:jni";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 0;
vm_args.options = options;
vm_args.ignoreUnrecognized = 0;
int ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
if(ret < 0) {
printf("\nUnable to Launch JVM\n");
exit(1);
}
if ( env->ExceptionCheck() == JNI_TRUE ) {
printf("exception\n");
exit(1);
}
}
void f() {
printf("inside...\n");
//eat up a few megs of stack
char stackTest[0x2FFFFF];
printf("...returning");
}
int main(int argc, char* argv[]) {
JavaVM * jvm;
CreateVM(&jvm);
f();
printf("exiting...\n");
return 0;
}构建命令:
-I/import/bitbucket/JDK/jdk1.6.0_26/include/linux -L/import/bitbucket/JDK/jdk1.6.0_26/jre/lib/amd64 -L/import/bitbucket/JDK/jdk1.6.0_26/jre/lib/amd64/server -m64 CTest.cpp -I/import/bitbucket/JDK/jdk1.6.0_26/ g++ -ljava -ljvm
发布于 2011-08-22 22:03:29
您的堆栈食人看起来很麻烦,但如果使用-O0,就不会了。
另外,sun上的JVM可能会有所不同,或者在solaris上运行时可以使用较少的堆栈空间。
如何在Linux和Solaris上限制堆栈大小?
更新:是的,JVM使用操作系统Solaris和on上的不同设置:
-XX:ThreadStackSize=512线程堆栈大小(以字节为单位)。(0表示使用默认堆栈大小) Sparc: 512;Solaris x86: 320 ( 5.0及更早版本为256个);Sparc 64位: 1024;Linux amd64: 1024 ( 5.0及更早版本为0 );所有其他值为0。
我不知道主线程的设置是什么,但这表明solaris将使用与linux不同的内存设置。
=== UPDATE2
JNI_CreateJavaVM中的第一个操作是线程创建,因为线程创建本身是高度线程化的:
result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again);
if (result == JNI_OK) {
JavaThread *thread = JavaThread::current();
/* thread is thread_in_vm here */
*vm = (JavaVM *)(&main_vm);因此,线程是在CreateJavaVM调用中创建的。
更改"CompilerThreadStackSize“全局变量,因为(!为什么编辑时没有草稿自动保存??)
默认情况下,AMD64 Linux,JVM有4M编译器线程堆栈和Solaris SPARC64 64有200万编译器线程堆栈。通常的线程在linux上有1M个堆栈,在Solaris上有2M个堆栈。
使用1限制linux上的编译器堆栈大小
-XX:CompilerThreadStackSize以调整堆栈大小
该值以kb为单位。在这两个操作系统上尝试将其设置为2048。
发布于 2011-08-25 19:42:26
好的。现在,我可以在f()中复制一个SIGSEGV;我使用的是i386 jvm,而且更老一些。让我们调试内存分配。
$ cat gdb.how
b main
r
b mmap
commands
x/x $sp+4
x/x $sp+8
bt
c
end
c您可以将$sp+4和$sp+8更改为+8和+16或类似。gdb的第一个输出应该是"00000000,00001000“。我建议您为jvm设置调试符(我有)。
$ gdb -x gdb.how ./a.out > gdb.log
quit
y现在,让我们查看如何为线程分配内存:
$ grep Breakpoint\ 2, -A4 gdb.log | grep pthread_create -B 2 | grep 0x00 |cut -d : -f 2 |
perl -e '$a=0;while(<>){s/0x0//;$a+=$_;};print "ibase=16\n".uc($a)."\n";'|bc
4616192它是所有线程堆栈大小的总和。您可以删除此命令的某些部分来查看实际分配,我使用Sun创建了7个线程。
现在您可以尝试更改一些选项并检查为线程堆栈分配了多少内存。
我得到的..。这很有趣。我的ulimit -s是8192。如果我用./a.out开始使用./a.out,我会得到一个SEGV
$ ./a.out
Segmentation fault但是,如果我确实以(./a.out ) (bash-subshell中的start )开始,则没有分段错误。
https://stackoverflow.com/questions/7153177
复制相似问题