Java端对JNI / C ++库的并发访问

时间:2018-10-04 00:34:01

标签: java c++ java-native-interface

由于某些错误涉及在c ++库中执行复杂的读取操作,因此我无法通过一些最小的工作示例来重现该错误。尽管如此,我还是进行了一些测试,可以描述两种可能的配置的结果。

我有一些Java代码,它们通过类(即JNIClass)通过JNI访问c ++库,在文件(以二进制格式序列化)中执行查找。

JNIClass在应用于Java流的forEach方法的Consumer中使用。流可以是流,也可以是parallelStreams。我仅在此类流是并行流时才注意到一些错误,并且c ++库仅对串行化数据结构执行读取和二进制搜索,并且未分配堆分配数据结构。线程之间唯一共享的是一些用于二进制搜索比较的函数指针。因此,我想知道为什么在Java中返回查询结果的只读操作会导致此类问题。

我正在考虑一个可能的解决方案,但是我不知道在Java中是否可行:将c ++库解耦并将每个线程与另一个库文件相关联是否可以解决内存访问问题?二进制搜索的上述函数指针的共享是问题的根源吗?

编辑

核心转储(gdb java core):

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/usr/lib/jvm/java-8-oracle/bin/java -Xmx60g -javaagent:/media/giacomo/Data/Scar'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51  ../sysdeps/unix/sysv/linux/raise.c: File o directory non esistente.
[Current thread is 1 (Thread 0x7f48473ec700 (LWP 8542))]
(gdb) where
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007f57775a1801 in __GI_abort () at abort.c:79
#2  0x00007f5776e8e3c5 in os::abort(bool) () from /usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so
#3  0x00007f57770325b3 in VMError::report_and_die() () from /usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so
#4  0x00007f5776e9470f in JVM_handle_linux_signal () from /usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so
#5  0x00007f5776e8a653 in signalHandler(int, siginfo*, void*) () from /usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so
#6  <signal handler called>
#7  0x00007f48462ffb4d in SLHM_Secondary::searchForId (this=0x7f47640179b8, toSearch="elias delta coding") at /home/giacomo/CLionProjects/edgeindexing/fmatch/StringLongHashMultimapIndexer/SLHM_Secondary.cpp:34
#8  0x00007f4846300c14 in FuzzyMatch_FDContainer::rankCollectionOf (this=0x7f47640179b8, k=std::unordered_set with 368560 elements = {...}, m1=std::unordered_map with 10 elements = {...}, size=10, 
    threshold=0.69999999999999996, pollMap=...) at /home/giacomo/CLionProjects/edgeindexing/fmatch/FuzzyMatch_FDContainer.cpp:123
#9  0x00007f4846301483 in FuzzyMatch_FDContainer::fuzzyMatch (this=0x7f47640179b8, threshold=0.69999999999999996, topk=3, objectString="105th Brigade", result=std::multimap with 0 elements)
    at /home/giacomo/CLionProjects/edgeindexing/fmatch/FuzzyMatch_FDContainer.cpp:181
#10 0x00007f4846301792 in FuzzyMatch_FDContainer::fuzzyMatch (this=0x7f47640179b8, threshold=0.69999999999999996, topk=3, objectStrings="105th Brigade")
    at /home/giacomo/CLionProjects/edgeindexing/fmatch/FuzzyMatch_FDContainer.cpp:213
#11 0x00007f48462e82dc in Java_org_ufl_hypogator_jackb_fuzzymatching_TwoGramIndexerJNI_fuzzyMatch (env=0x7f475c0029f8, self=0x7f48473ead48, dim=0x7f48473ead40, threshold=0.69999999999999996, topk=3, 
    term=0x7f48473ead20) at /home/giacomo/CLionProjects/edgeindexing/fmatch/libfuzzymatch.cpp:48
#12 0x00007f5761018687 in ?? ()
#13 0x00007f48473eac90 in ?? ()
#14 0x00007f484f906ad0 in ?? ()
#15 0x00007f48473eacf0 in ?? ()
#16 0x00007f484f9089a8 in ?? ()
#17 0x0000000000000000 in ?? ()

.log文件中的堆栈信息:

Stack: [0x00007f71eb8fd000,0x00007f71eb9fe000],  sp=0x00007f71eb9fa620,  free space=1013k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libc.so.6+0x97207]  __libc_malloc+0x197

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  sun.misc.Unsafe.defineAnonymousClass(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;+0
j  java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass()Ljava/lang/Class;+511
j  java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite()Ljava/lang/invoke/CallSite;+1
j  java.lang.invoke.LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;+31
j  java.lang.invoke.LambdaForm$DMH.invokeStatic_L6_L(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+20
j  java.lang.invoke.LambdaForm$BMH.reinvoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+79
j  java.lang.invoke.LambdaForm$MH.invoke_MT(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+30
j  java.lang.invoke.CallSite.makeSite(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/invoke/CallSite;+184
j  java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(Ljava/lang/Class;Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;+6
j  java.lang.invoke.MethodHandleNatives.linkCallSite(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;+45
v  ~StubRoutines::call_stub
j  org.ufl.hypogator.jackb.scraper.adt.DiGraphEquivalenceClass.loadFromFile2(Ljava/io/File;Lorg/ufl/hypogator/jackb/disambiguation/dimension/concept/ConceptNetVocabulary;Ljava/util/function/Function;)V+11
j  org.ufl.hypogator.jackb.fuzzymatching.TwoGramIndexerJNI$TwoGramIndexerForDimension.<init>(Lorg/ufl/hypogator/jackb/fuzzymatching/TwoGramIndexerJNI;Ljava/lang/String;Lorg/ufl/hypogator/jackb/fuzzymatching/TwoGramIndexerJNI;)V+89
j  org.ufl.hypogator.jackb.fuzzymatching.TwoGramIndexerJNI.openDimension(Ljava/lang/String;)Lorg/ufl/hypogator/jackb/fuzzymatching/TwoGramIndexerJNI$TwoGramIndexerForDimension;+25
j  org.ufl.hypogator.jackb.scraper.MultiConceptScraper$PrivateTermScorer.<init>(Lorg/ufl/hypogator/jackb/scraper/MultiConceptScraper;Ljava/lang/String;Z)V+39
j  org.ufl.hypogator.jackb.scraper.MultiConceptScraper.dimension(Ljava/lang/String;Z)Lorg/ufl/hypogator/jackb/scraper/TermScorer;+7
j  org.ufl.hypogator.jackb.disambiguation.dimension.concept.ConceptNetDimensionDisambiguationOperations.<init>(Ljava/lang/String;)V+57
j  org.ufl.hypogator.jackb.disambiguation.dimension.concept.DisambiguatorForDimensionForConcept.<init>(Ljava/lang/String;)V+2
j  org.ufl.hypogator.jackb.disambiguation.dimension.concept.DimConcepts.<init>(Ljava/lang/String;)V+15
j  org.ufl.hypogator.jackb.inconsistency.legacy.TupleComparator.generateFromType(Ljava/lang/String;)Lorg/ufl/hypogator/jackb/comparators/partialOrders/InformationPreservingComparator;+117
j  org.ufl.hypogator.jackb.m9.CompareOnce.lambda$memoizeTypeComparisons$2(Lorg/jooq/Record;)V+13
j  org.ufl.hypogator.jackb.m9.CompareOnce$$Lambda$14.accept(Ljava/lang/Object;)V+4
j  java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Ljava/lang/Object;)V+5
j  java.util.Spliterators$ArraySpliterator.forEachRemaining(Ljava/util/function/Consumer;)V+53
j  java.util.stream.AbstractPipeline.copyInto(Ljava/util/stream/Sink;Ljava/util/Spliterator;)V+32
j  java.util.stream.ForEachOps$ForEachTask.compute()V+103
j  java.util.concurrent.CountedCompleter.exec()Z+1
j  java.util.concurrent.ForkJoinTask.doExec()I+10
j  java.util.concurrent.ForkJoinPool$WorkQueue.runTask(Ljava/util/concurrent/ForkJoinTask;)V+21
j  java.util.concurrent.ForkJoinPool.runWorker(Ljava/util/concurrent/ForkJoinPool$WorkQueue;)V+35
j  java.util.concurrent.ForkJoinWorkerThread.run()V+24
v  ~StubRoutines::call_stub

最后一行是searchForId的代码,导致错误:

void *SLHM_Secondary::searchForId(std::string &toSearch) {
    LONG_NUMERIC hash = hashf(toSearch);
    struct long_index_file toSearchVehicle{};
    toSearchVehicle.id = hash;
    struct long_index_file* ptr = binVectorFixedSizeArray<struct long_index_file>(pimarySparseIndex, primarySize, &toSearchVehicle, &findLongIndexOffset);
    if (ptr == nullptr) return nullptr;
    LONG_NUMERIC* offsets = (LONG_NUMERIC*)(this->element+ptr->offset);
    LONG_NUMERIC n               = offsets[0]; // Line 34

0 个答案:

没有答案