首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNA/BridJ等故障的分割

JNA/BridJ等故障的分割
EN

Stack Overflow用户
提问于 2016-02-23 03:33:15
回答 1查看 678关注 0票数 2

我多次使用JNI、JNA、BridJ和JavaCPP重新构建我的Java/C++项目,每次我遇到随机(不可预测的)分段错误。我已经验证了使用此库的纯C++可执行文件不会导致分段错误,在BridJ的情况下,通过显式调用它将其缩小为Java的垃圾收集器。

其中一个想法是,这些库正在创建Java端指针对象,当它们(通过free )收集垃圾时调用deletefinalize,而不是像在这个应用程序中那样将C++返回的指针当作借来的引用来处理。

但我尝试了一个额外的测试(如下所示):我将API中的每个指针转换为int64_t (long in C++ ),并在C++中显式地转换为合适的类型。我仍然能看到罕见的节段断层。

所以我的问题很广泛:是什么导致了这个问题?我将使用JNA或BridJ接受答案,因为我可以轻松地在这两者之间切换。我想我忽略了一个根本性的问题,因为这个问题在我尝试过的所有库中都很普遍。

为了具体起见,这是我的JNA版本。我将链接到CERN根库。H是:

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

RootTreeReader.cpp是:

代码语言:javascript
复制
#include <string>

#include "RootTreeReader.h"

TFile *newFile(const char *fileLocation) {
  return TFile::Open(fileLocation);
}

TTreeReader *newReader(TFile *file, const char *treeLocation) {
  return new TTreeReader(treeLocation, file);
}

bool readerNext(TTreeReader *reader) {
  return reader->Next();
}

TTreeReaderValueBase *newValue_float(TTreeReader *reader, const char *name) {
  return new TTreeReaderValue<float>(*reader, name);
}

float getValue_float(TTreeReaderValueBase *value) {
  return *((float*)value->GetAddress());
}

他们的制造文件是

代码语言:javascript
复制
all: RootTreeReader.cpp
    mkdir -p ../../../target/native/linux-x86-64
    g++ RootTreeReader.cpp -o ../../../target/native/linux-x86-64/libRootTreeReader.so \
        -fPIC -shared \
        -Wl,--no-as-needed $(shell root-config --cflags --ldflags --libs) -lTreePlayer

JNAerator生成以下RootTreeReaderLibrary.java:

代码语言:javascript
复制
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();
        }
    };
}

我这样叫它:

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

它的分段错误很少有显式的垃圾收集器调用或不存在。这个分段错误的BridJ版本很少没有并且经常使用显式的垃圾收集器调用。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-26 08:57:06

快速解决办法:

代码语言:javascript
复制
export LD_PRELOAD=/path/to/libjsig.so

问题是CERN根试图为与JDK相同的信号安装处理程序。甲骨文建议预加载libjsig.so,它提供了一个“信号链接工具”,以解决以下问题:

https://docs.oracle.com/javase/6/docs/technotes/guides/vm/signal-chaining.html

编辑吉姆:

对于根框架,可以通过调用

代码语言:javascript
复制
gSystem->ResetSignals();

讨论可以在根留言板上找到:https://root.cern.ch/phpBB3/viewtopic.php?t=8231

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

https://stackoverflow.com/questions/35568318

复制
相关文章

相似问题

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