Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.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 为什么我会得到;存储错误“;在JVM下运行时在我的Ada共享库上_Java_Linux_Segmentation Fault_Ada_Gnat - Fatal编程技术网

Java 为什么我会得到;存储错误“;在JVM下运行时在我的Ada共享库上

Java 为什么我会得到;存储错误“;在JVM下运行时在我的Ada共享库上,java,linux,segmentation-fault,ada,gnat,Java,Linux,Segmentation Fault,Ada,Gnat,我们有一个由gnatpro19.2编译的Ada共享库,我们通过JNA调用调用它 我们的应用程序在windows下运行良好。在Linux下移植时,应用程序会随机崩溃,出现Ada异常: storage error or erroneous memory access. 使用gdb(附加进程)进行调试没有多大帮助。我们得到了各种SIGSEGV,我们继续,过了一会儿,我们得到了没有可用调用堆栈的存储错误 我们的共享库可以与python本机调用一起使用,没有任何问题。问题可能在Java方面 没有运气就尝

我们有一个由gnatpro19.2编译的Ada共享库,我们通过JNA调用调用它

我们的应用程序在windows下运行良好。在Linux下移植时,应用程序会随机崩溃,出现Ada异常:

storage error or erroneous memory access.
使用gdb(附加进程)进行调试没有多大帮助。我们得到了各种SIGSEGV,我们继续,过了一会儿,我们得到了没有可用调用堆栈的存储错误

我们的共享库可以与python本机调用一起使用,没有任何问题。问题可能在Java方面

没有运气就尝试切换JVM(openjdk或官方jdk)


为什么会这样?有办法解决吗?

第一个提示是,在尝试将调试器附加到应用程序时,会得到一堆SIGSEGV,然后在继续时看到程序正在恢复

这意味着SIGSEGV信号在Java端处理,如中所确认

Java使用推测性加载。如果指针指向可寻址内存,则加载成功。指针很少不指向可寻址内存,尝试的加载会生成SIGSEGV。。。哪个java运行时截取,使内存再次可寻址,并重新启动load指令

现在发生的是,默认情况下,GNAT运行时安装一个新的信号处理程序来捕获SIGSEGV并重定向到一个干净的Ada异常。Ada异常的一个有趣特性是,即使没有调试器,它们也可以打印堆栈跟踪。此SIGSEGV处理程序重定向允许此操作

但是在Java的情况下,由于Java使用推测性加载,所以在Java端经常需要SIGSEGV。因此,当加载并初始化Ada共享库时,将安装Ada SIGSEGV处理程序,并捕获那些“正常”SIGSEGV,并立即中止

请注意,它不会发生在Windows下。java运行时在处理内存冲突访问时,由于Windows的限制,可能无法使用这种推测性加载机制

信号处理在
s-intman.adb中完成

 --  Check that treatment of exception propagation here is consistent with
  --  treatment of the abort signal in System.Task_Primitives.Operations.

  case signo is
     when SIGFPE  => raise Constraint_Error;
     when SIGILL  => raise Program_Error;
  --   when SIGSEGV => raise Storage_Error;  -- commenting this line should fix it
     when SIGBUS  => raise Storage_Error;
     when others  => null;
  end case;
end Notify_Exception;
现在我们必须重新构建一个新的本机运行时,并使用它来代替默认运行时。这是相当乏味和容易出错的。该文件是gnarl库的一部分。我们必须使用适当的选项
-gnatp-nostinc-O2-fPIC
动态地重建gnarl库,以创建gnatrl库替换。。。在升级编译器时再次执行此操作

幸运的是,AdaCore提供了另一种解决方案:

首先在
.gpr
项目目录中创建一个pragmas文件(我们称之为
no_sigsegv.adc
),其中包含:

pragma Interrupt_State (SIGSEGV, SYSTEM); 
指示运行时不安装SIGSEGV处理程序

然后将其添加到
.gpr
文件的
编译器
包中:

  package Compiler is
    ...
      for local_configuration_pragmas use Project'Project_dir & "/no_sigsegv.adc";

从零开始重建一切。测试:没有任何崩溃。

我在寻找pragma配置文件的真实用例,比如3天前:)如果我理解正确的话:[SIGSEGV while debug]和[initial storage error problems]都消失了,不是吗?SIGSEGV while debug仍然存在。这是Java问题,不是Ada问题。但是我们不需要调试应用程序,因为它可以工作:),如果它失败,我们可以从windows端调试它,java不使用它mechanism@LoneWanderer链接答案的解决方法是:
(gdb)handle SIGSEGV nostop noprint pass
。这样你就可以调试你的应用程序而不会被虚假的SIGSEGV打断。大多数情况下,Ada程序不会触发SIGSEGV。也就是说,如果一直启用ada运行时检查。