首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >linux上的JNI_CreateJavaVM破坏堆栈?

linux上的JNI_CreateJavaVM破坏堆栈?
EN

Stack Overflow用户
提问于 2011-08-22 20:25:16
回答 2查看 1.5K关注 0票数 4

这发生在Linux2.6.18-238.5.1.el5和64位应用程序上。我的进程堆栈大小是10 My。但是,在对JNI_CreateJavaVM进行(成功)调用后,堆栈上似乎只剩下1-2 MB。如果我通过它-我的记忆错误,好像我是溢出堆栈。

几个注意事项:

  1. 如果我不创建JVM,那么我就可以访问整个我的10 my堆栈。
  2. 即使调用JVM,在Solaris上运行相同makefile的相同测试程序也很好。

测试来源:

代码语言:javascript
复制
#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

EN

回答 2

Stack Overflow用户

发布于 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中的第一个操作是线程创建,因为线程创建本身是高度线程化的:

代码语言:javascript
复制
  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。

票数 0
EN

Stack Overflow用户

发布于 2011-08-25 19:42:26

好的。现在,我可以在f()中复制一个SIGSEGV;我使用的是i386 jvm,而且更老一些。让我们调试内存分配。

代码语言:javascript
复制
$ 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设置调试符(我有)。

代码语言:javascript
复制
$ gdb  -x gdb.how ./a.out  > gdb.log
quit
y

现在,让我们查看如何为线程分配内存:

代码语言:javascript
复制
$ 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

代码语言:javascript
复制
$ ./a.out
Segmentation fault

但是,如果我确实以(./a.out ) (bash-subshell中的start )开始,则没有分段错误。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7153177

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档