Java JNA/BridJ等中的分段错误
我已经多次使用JNI、JNA、BridJ和JavaCPP重建了Java/C++项目,每次遇到随机(不可预测的)分段错误时。我已经验证了使用该库的纯C++可执行文件不会导致分段错误,在BridJ的例子中,通过显式调用它将其缩小到Java的垃圾收集器Java JNA/BridJ等中的分段错误,java,c++,jna,javacpp,bridj,Java,C++,Jna,Javacpp,Bridj,我已经多次使用JNI、JNA、BridJ和JavaCPP重建了Java/C++项目,每次遇到随机(不可预测的)分段错误时。我已经验证了使用该库的纯C++可执行文件不会导致分段错误,在BridJ的例子中,通过显式调用它将其缩小到Java的垃圾收集器 一种思想是,当这些程序在垃圾收集时(通过最终确定 >而不是处理C++返回的引用指针,正如在本应用程序中所使用的那样,创建java侧指针对象,调用代码< >免费>代码>或代码>删除>代码>。 但是我已经尝试了一个附加的测试(没有在下面表示):我把API中
一种思想是,当这些程序在垃圾收集时(通过<代码>最终确定<代码> >而不是处理C++返回的引用指针,正如在本应用程序中所使用的那样,创建java侧指针对象,调用代码< >免费>代码>或代码>删除>代码>。
但是我已经尝试了一个附加的测试(没有在下面表示):我把API中的每个指针都变成了<代码>爪哇的It64,t/Cube >(<代码>长< /Cord>),并在C++中显式地作为适当的类型。我仍然能看到罕见的断层
所以我的问题很广泛:是什么导致了这个问题?我将接受使用JNA或BridJ的答案,因为我可以轻松地在这两者之间切换。我想我遗漏了一个基本问题,因为这个问题在我尝试过的所有图书馆中都非常普遍 具体来说,这里是我的JNA版本。我正在链接CERN根库。RootTreeReader.h是:#ifndef ROOTTREEREADER_H
#define ROOTTREEREADER_H
#include <TFile.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <TTreeReaderArray.h>
using namespace ROOT::Internal;
extern "C" {
TFile *newFile(const char *fileLocation);
TTreeReader *newReader(TFile *file, const char *treeLocation);
bool readerNext(TTreeReader *reader);
TTreeReaderValueBase *newValue_float(TTreeReader *reader, const char *name);
float getValue_float(TTreeReaderValueBase *value);
}
#endif // ROOTTREEREADER_H
Jnavior生成以下RootTreeReaderLibrary.java:
package org.dianahep.scaroot;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
/**
* JNA Wrapper for library <b>RootTreeReader</b><br>
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>
* a tool written by <a href="http://ochafik.com/">Olivier Chafik</a> that <a href="http://code.google.com/p/jnaerator/wiki/CreditsAndLicense">uses a few opensource projects.</a>.<br>
* For help, please visit <a href="http://nativelibs4java.googlecode.com/">NativeLibs4Java</a> , <a href="http://rococoa.dev.java.net/">Rococoa</a>, or <a href="http://jna.dev.java.net/">JNA</a>.
*/
public interface RootTreeReaderLibrary extends Library {
public static final String JNA_LIBRARY_NAME = "RootTreeReader";
public static final NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance(RootTreeReaderLibrary.JNA_LIBRARY_NAME);
public static final RootTreeReaderLibrary INSTANCE = (RootTreeReaderLibrary)Native.loadLibrary(RootTreeReaderLibrary.JNA_LIBRARY_NAME, RootTreeReaderLibrary.class);
/**
* Original signature : <code>TFile* newFile(const char*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:5</i><br>
* @deprecated use the safer methods {@link #newFile(java.lang.String)} and {@link #newFile(com.sun.jna.Pointer)} instead
*/
@Deprecated
RootTreeReaderLibrary.TFile newFile(Pointer fileLocation);
/**
* Original signature : <code>TFile* newFile(const char*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:5</i>
*/
RootTreeReaderLibrary.TFile newFile(String fileLocation);
/**
* Original signature : <code>TTreeReader* newReader(TFile*, const char*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:6</i><br>
* @deprecated use the safer methods {@link #newReader(org.dianahep.scaroot.RootTreeReaderLibrary.TFile, java.lang.String)} and {@link #newReader(org.dianahep.scaroot.RootTreeReaderLibrary.TFile, com.sun.jna.Pointer)} instead
*/
@Deprecated
RootTreeReaderLibrary.TTreeReader newReader(RootTreeReaderLibrary.TFile file, Pointer treeLocation);
/**
* Original signature : <code>TTreeReader* newReader(TFile*, const char*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:6</i>
*/
RootTreeReaderLibrary.TTreeReader newReader(RootTreeReaderLibrary.TFile file, String treeLocation);
/**
* Original signature : <code>bool readerNext(TTreeReader*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:7</i>
*/
byte readerNext(RootTreeReaderLibrary.TTreeReader reader);
/**
* Original signature : <code>TTreeReaderValueBase* newValue_float(TTreeReader*, const char*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:9</i><br>
* @deprecated use the safer methods {@link #newValue_float(org.dianahep.scaroot.RootTreeReaderLibrary.TTreeReader, java.lang.String)} and {@link #newValue_float(org.dianahep.scaroot.RootTreeReaderLibrary.TTreeReader, com.sun.jna.Pointer)} instead
*/
@Deprecated
RootTreeReaderLibrary.TTreeReaderValueBase newValue_float(RootTreeReaderLibrary.TTreeReader reader, Pointer name);
/**
* Original signature : <code>TTreeReaderValueBase* newValue_float(TTreeReader*, const char*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:9</i>
*/
RootTreeReaderLibrary.TTreeReaderValueBase newValue_float(RootTreeReaderLibrary.TTreeReader reader, String name);
/**
* Original signature : <code>float getValue_float(TTreeReaderValueBase*)</code><br>
* <i>native declaration : src/main/cpp/RootTreeReader.h:11</i>
*/
float getValue_float(RootTreeReaderLibrary.TTreeReaderValueBase value);
public static class TFile extends PointerType {
public TFile(Pointer address) {
super(address);
}
public TFile() {
super();
}
};
public static class TTreeReader extends PointerType {
public TTreeReader(Pointer address) {
super(address);
}
public TTreeReader() {
super();
}
};
public static class TTreeReaderValueBase extends PointerType {
public TTreeReaderValueBase(Pointer address) {
super(address);
}
public TTreeReaderValueBase() {
super();
}
};
}
我这样称呼它:
Native.setProtected(true)
println("Native.isProtected", Native.isProtected) // it's true on Linux; I've tried this with and without
val lib = RootTreeReaderLibrary.INSTANCE
println("one")
val file = lib.newFile("TrackResonanceNtuple.root")
println("two")
val reader = lib.newReader(file, "TrackResonanceNtuple/twoMuon")
println("three")
val mass = lib.newValue_float(reader, "mass_mumu")
println("four")
var counter = 0
while (lib.readerNext(reader) > 0) {
val num = lib.getValue_float(mass)
println(num)
counter += 1
// if (counter % 1000 == 0) {
// println("gc start")
// System.gc()
// println("gc end")
// }
}
println("five")
它很少在有或没有显式垃圾收集器调用的情况下发生故障。此SEGJ的BridJ版本很少在没有显式垃圾回收器调用的情况下出现故障,并且经常出现这种故障。快速修复:
export LD_PRELOAD=/path/to/libjsig.so
问题是CERN ROOT试图为与JDK相同的信号安装处理程序。Oracle建议预加载libjsig.so
,它提供了一个“信号链接工具”,以解决这些问题:
从Jim处编辑:
特别是对于根框架,您可以通过调用
gSystem->ResetSignals();
讨论可以在这个根留言板上找到:JNA将只释放它已分配的内存,并且它会在定义非常明确的位置释放内存(请参阅
Native.dispose()
,它引用了所有这些位置)。您可以有选择地禁用这些处理方法中的每一种,以确定是否涉及其中任何一种。您是否有我可以查看的JavaCPP版本?我尝试了JavaCPP 1.1,尽管上面的示例是JNA。无论如何,文件
对象几乎可以保证被垃圾收集,因此,请确保您的库不需要它。信号处理程序似乎有问题:在大型库中经常发生
export LD_PRELOAD=/path/to/libjsig.so
gSystem->ResetSignals();