标签: java-native-interface

将本机指针存储在Java对象中的"正确"方法是什么?

将本机指针存储在Java对象中的"正确"方法是什么?

我可以将指针视为Java int,如果我碰巧知道本机指针的大小是<= 32位,或者long如果我碰巧知道本机指针的大小是<= 64位的话.但有没有更好或更清洁的方法来做到这一点?

编辑:从JNI函数返回一个指针原生到底是什么我也不想做.我宁愿返回一个代表本机资源的Java对象.但是,我返回的Java对象必须有一个包含指针的字段,这使我回到原始问题.

或者,是否有一些更好的方法让JNI函数返回对本机资源的引用?

java java-native-interface

24
推荐指数
2
解决办法
8417
查看次数

使用g ++进行链接无法搜索-lstdc ++

我正在尝试使用别人的Makefile来编译一个非常简单的c ++库.makefile如下:

JNIFLAGS=-O2 -pthread -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux

all:
    rm -f ../dist/libUtils.so
    g++ $(JNIFLAGS) -c -m32 -o com_markets_utils_dates_NativeTime.o com_markets_utils_dates_NativeTime.cpp
    g++ $(JNIFLAGS) -c -m32 -o DateUtil.o DateUtil.cpp
    g++ -pthread -m32 -shared -fPIC -o ../dist/libUtils.so DateUtil.cpp
    g++ -pthread -m32 -shared -fPIC -o ../dist/libNativeTime.so DateUtil.o com_markets_utils_dates_NativeTime.o
Run Code Online (Sandbox Code Playgroud)

这编译很好,但链接器抱怨:

...
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.4.1/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.4.1/libstdc++.a when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.4.1/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.4.1/libstdc++.a when searching for -lstdc++
/usr/bin/ld: cannot find -lstdc++
collect2: …
Run Code Online (Sandbox Code Playgroud)

java-native-interface linker makefile g++ libstdc++

24
推荐指数
3
解决办法
5万
查看次数

当Eclipse插件使用JNI时,如何将JNI控制台输出重定向到Eclipse Console视图?

我有一个Eclipse插件(A),它依赖于另一个插件(B).插件B只是一个jar包装器,它包含一个本机dll,并执行jni功能.鉴于此设置,我在A的Activator类的start方法中有以下代码:

MessageConsole jniConsole = new MessageConsole("Opereffa Output", null);
ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { jniConsole });
ConsolePlugin.getDefault().getConsoleManager().showConsoleView(jniConsole);
MessageConsoleStream stream = jniConsole.newMessageStream();
System.setOut(new PrintStream(stream));
System.setErr(new PrintStream(stream));
Run Code Online (Sandbox Code Playgroud)

当插件A执行其功能时,System.out的任何使用实际上都会进入Eclipse中的控制台.但是JNI使用的本机代码也会写入输出流,这是我无法抓取的.在开发期间,JNI的输出转到Eclipse实例的控制台,该实例已启动包含插件的运行实例.

那么如何获取JNI输出并在控制台中显示?

eclipse console java-native-interface plugins redirect

24
推荐指数
1
解决办法
2029
查看次数

当我从本机Java方法抛出C++异常时会发生什么?

假设我将Sun的JVM嵌入到C++应用程序中.通过JNI,我调用了一个Java方法(我自己的),它又调用了我在共享库中实现的本机方法.

如果此本机方法抛出C++异常会发生什么?

编辑:编译器是gcc 3.4.x,jvm是sun的1.6.20.

c++ java linux java-native-interface exception

24
推荐指数
2
解决办法
9914
查看次数

使用包含名为"Node"的类的JNI C++代码,JVM无法正常工作

我自己和一些队友一直无法理解为什么下面的代码片段在使用JVM版本1.6u23到1.6u31(本帖子的最新版本)时不能提供正确的输出.此代码段代表了一个更大问题的简化:

更新:稍微修改了示例,重点关注"virtual_function()"似乎没有被调用的问题.

更新:根据迄今为止的评论更简化示例.

NodeTester.cpp:

#include <iostream>
#include <jni.h>

class Node {
  public:
    Node () :m_counter(0) {}
    virtual ~Node () {}

    virtual void virtual_function () {
      m_counter += 10;
    }

    void non_virtual_function () {
      m_counter += 1;
    }

    int get_counter () {
      return m_counter;
    }

  private:
    int m_counter;

};

extern "C" {
  JNIEXPORT void JNICALL Java_NodeTester_testNode (JNIEnv *jni_env_rptr, 
                                                   jclass java_class) {
    Node *node_rptr = new Node();
    node_rptr->non_virtual_function();
    node_rptr->virtual_function();

    std::cout << node_rptr->get_counter() << std::endl;

    delete node_rptr;
  }
}
Run Code Online (Sandbox Code Playgroud)

NodeTester.java:

public class NodeTester …
Run Code Online (Sandbox Code Playgroud)

c++ java java-native-interface

24
推荐指数
2
解决办法
1838
查看次数

谁在ubuntu服务器上神秘地发送了一个SIGKILL到我的进程

10月25日更新:

现在我发现了导致问题的原因.

1)子进程自杀,这就是strace/perf/auditctl无法跟踪它的原因.

2)从Java线程触发创建进程的JNI调用.当线程最终死亡时,它也会破坏它创建的进程.

3)在我的代码fork和execve()子进程中,我有代码来监视父进程死亡并使用以下行终止我的子进程:prctl(PR_SET_PDEATHSIG,SIGKILL); 我的错,我没有特别注意这个标志在b/c之前它被认为是我的其他项目的最佳实践,其中子进程从主线程分叉.

4)如果我注释掉这一行,问题就消失了.最初的目的是在父进程消失时终止子进程.即使没有这个标志,它仍然是正确的行为.好像是ubuntu框的默认行为.

5)最后发现它是一个内核bug,在内核版本3.4.0中修复,我在AWS上的ubuntu框是内核版本3.13.0-29-generic.

这些问题有几个有用的链接:

a)http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

b)在父线程退出时调用prctl(PR_SET_PDEATHSIG,SIGNAL),而不是父进程退出.

c)https://bugzilla.kernel.org/show_bug.cgi?id=43300

10月15日更新:

非常感谢所有的建议.我正在调查系统的一个区域到另一个区域.很难找到理由.

我想知道两件事.1)为什么像strace,auditctl和perf脚本这样强大的工具无法追踪导致杀戮的人?

2)被SIGKILL +++杀死的+++真的意味着它被信号杀死了吗?

原始邮政

我从Ubuntu 12中的Java应用程序服务器通过JNI接口启动了一个长时间运行的C进程.我使用JNI接口来启动进程而不是通过Java的进程构建器的原因是b/c的性能原因.对于java进程构建器来说,使用IPC非常低效,特别是b/c额外的缓冲引入了很长的延迟.

它会定期被SIGKILL神秘地终止.我发现的方式是通过strace,它说:"+++被SIGKILL +++杀死"

我检查了以下内容:

  1. 这不是崩溃.
  2. 这不是OOM.dmesg没什么.我的进程仅占用1 GB内存的3.3%.
  3. Java层没有杀死进程.如果代码终止进程,我会在JNI代码中放入一个日志,但是没有写入日志来指示.
  4. 这不是许可问题.我试图以sudo或其他用户身份运行,这两种情况都会导致进程被杀死.
  5. 如果我在shell中本地运行进程,一切正常.更重要的是,在我长时间运行的C代码中,我忽略了信号SIGHUP.只有当它作为Java服务器的子进程运行时,才会被杀死.
  6. 该过程非常耗费CPU.它使用了30%的CPU.有很多自愿上下文切换和nonvoluntary_ctxt_switches.
  7. (新更新)一个重要的事情很可能与我的进程被杀的原因有关.如果这个过程做了一些繁重的工作,它就不会被杀死,但是,有时它会做很少的CPU密集工作.当发生这种情况时,过了一会儿,大概1分钟就会被杀死.它的状态始终是S(睡眠)而不是R(跑步).操作系统似乎决定在大多数时间处于空闲状态时终止进程,如果进程繁忙则不会终止进程.
  8. 我怀疑Java的GC是罪魁祸首,然而,Java绝不会垃圾收集与JNI相关联的单例对象.(我的JNI对象与该单例绑定).

我被它终止的原因感到困惑.有没有人有一个很好的建议如何追踪它?

PS

  1. 在我的ubuntu限制 - 结果是:

    core file size          (blocks, -c) 0
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 7862
    max locked memory       (kbytes, -l) 64
    max memory size         (kbytes, -m) unlimited
    open files …
    Run Code Online (Sandbox Code Playgroud)

c java linux ubuntu java-native-interface

24
推荐指数
2
解决办法
9046
查看次数

使用Android Studio调试C++库

我正在开发一个Android项目,该项目使用一个Java类库作为包装器C++.C++库是一个公司内部库,我们可以访问它的源代码,但在Android项目中它只是动态链接的,所以它只能以头文件(.h)和共享对象(.so)的形式使用.有权访问库源代码,是否可以向Android Studio指定源代码的路径,以便我可以使用调试器进入库内部?

调试器工作,我可以进入Java_clory_engine_sdk_CloryNative_nativeInit函数内部,但我还想进一步调试对应于Clory::Engine该类的库,正如我所提到的,它是一个我们有源代码访问的内部库.

c_clory

例如,Clory::Engine::instance是库的一部分,我想向Android Studio指定CloryEngine.cpp文件的位置,以便我可以Clory::Engine::instance使用调试器进入内部,从而调试此静态成员函数.

我使用的是Android Studio 3.1.4.

这可能吗?

编辑:

clory-sdk.gradle文件指定CMakeLists.txt配置C++层的文件.

externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我使用的是使用Clory SDK的内部应用程序.在app.gradle我使用的文件内:

dependencies {
...
    compile project(':clory-sdk-core')
    compile project(':clory-sdk')
...
}
Run Code Online (Sandbox Code Playgroud)

所以我不认为我们在项目中使用aars app.gradle.该aars的运到客户端,但我们使用app.gradle的项目在这之前测试我们的小SDK功能.JNI层位于clory-sdk-core项目内部.

编辑2:

这是CMakeLists.txt处理JNI层的:

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_BUILD_TYPE …
Run Code Online (Sandbox Code Playgroud)

c++ java-native-interface android android-studio android-studio-3.0

24
推荐指数
2
解决办法
2081
查看次数

本机代码 - 如何以编程方式获取函数调用堆栈(回溯)

我在Android上运行C++代码库,并希望用户发送崩溃报告.

我正在使用ACRA库,它可以很好地用于Java代码,但是当本机代码崩溃时,我得不到足够的信息.实际上我想收到本机函数调用的堆栈跟踪.我知道在我的进程结束后会将崩溃信息打印到logcat中,我可以配置ACRA来读取/发送logcat.我已经设置了我的代码,使用信号处理程序检测本机崩溃,并回调Java以便ACRA报告.它也很好用.

然而,这种方法的时机不合适 - ACRA在崩溃进程仍然存活时读取日志,并且在崩溃进程完全结束后,Android(不确切知道哪个部分)将崩溃报告写入logcat.所以我在使用ACRA时没有收到堆栈跟踪.

所以我正在寻找一种以编程方式从C++代码中读取当前堆栈跟踪的方法,并将此信息提供给ACRA(或者其他崩溃报告工具).

我只需要写一些写入logcat的报告:

10-10 08:29:13.868: INFO/DEBUG(1121):          #00  pc 0003fc7c  /data/data/com.ex.lib/libapp.so
10-10 08:29:13.891: INFO/DEBUG(1121):          #04  pc 00016df4  /system/lib/libdvm.so
10-10 08:29:13.891: INFO/DEBUG(1121):          #05  pc 00045284  /system/lib/libdvm.so
10-10 08:29:13.899: INFO/DEBUG(1121):          #15  pc 00047c56  /system/lib/libdvm.so
10-10 08:29:13.922: INFO/DEBUG(1121):          #16  pc 00030e4c  /system/lib/libandroid_runtime.so
Run Code Online (Sandbox Code Playgroud)

有没有办法从我的代码中获取这个堆栈跟踪?

java-native-interface android acra

23
推荐指数
2
解决办法
6089
查看次数

通过JNI从不同的线程调用保存的java对象

我有一个java对象,它通过JNI调用C++共享对象.在C++中,我保存了对JNIEnv和jObject的引用.

JavaVM * jvm;
JNIEnv * myEnv;
jobject myobj;

JNIEXPORT void JNICALL Java_org_api_init
   (JNIEnv *env, jobject jObj) {
    myEnv = env;
    myobj = jObj;
}
Run Code Online (Sandbox Code Playgroud)

我还有一个GLSurface渲染器,它最终在另一个线程GLThread上调用上面提到的C++共享对象.然后我尝试使用我最初保存的jobject回调到我的原始Java对象,但我想因为我在GLThread上,我得到以下错误.

W/dalvikvm(16101): JNI WARNING: 0x41ded218 is not a valid JNI reference
I/dalvikvm(16101): "GLThread 981" prio=5 tid=15 RUNNABLE
I/dalvikvm(16101):   | group="main" sCount=0 dsCount=0 obj=0x41d6e220 self=0x5cb11078
I/dalvikvm(16101):   | sysTid=16133 nice=0 sched=0/0 cgrp=apps handle=1555429136
I/dalvikvm(16101):   | schedstat=( 0 0 0 ) utm=42 stm=32 core=1
Run Code Online (Sandbox Code Playgroud)

回调Java的代码:

void setData()
    {
        jvm->AttachCurrentThread(&myEnv, 0);

        jclass javaClass = myEnv->FindClass("com/myapp/myClass");
        if(javaClass == …
Run Code Online (Sandbox Code Playgroud)

c++ java java-native-interface android android-ndk

23
推荐指数
1
解决办法
8134
查看次数

在本地复制和解决Android java.lang.unsatisfiedLinkError

我和一个朋友一起创建了一个Android应用来组织学校成绩。该应用程序可以在我的设备和大多数用户设备上正常运行,但是崩溃率超过3%,这主要是由于java.lang.UnsatisfiedLinkErrorAndroid 7.0、8.1和9版本所发生的。

我已经在手机和包括所有架构在内的多个仿真器上测试了该应用程序。我将应用程序作为android-app-bundle上传到应用程序商店,并怀疑这可能是问题的根源。

我在这里有点迷茫,因为我已经尝试了好几件事,但是到目前为止,我既不能减少出现的次数,也无法在任何设备上重现它。任何帮助将不胜感激。

我发现此资源指出Android有时无法解压缩外部库。因此,他们创建了一个ReLinker库,该库将尝试从压缩的应用程序中获取库:

不幸的是,这并没有减少由于导致的崩溃数量java.lang.UnsatisfiedLinkError。我继续在线研究并找到了这篇文章,这表明问题出在64位库中。因此,我删除了64位库(该应用程序仍可在所有设备上运行,因为64位架构也可以执行32位库)。但是,错误仍然会以与以前相同的频率发生。

通过google-play-console,我得到了以下崩溃报告:

java.lang.UnsatisfiedLinkError: 
at ch.fidelisfactory.pluspoints.Core.Wrapper.callCoreEndpointJNI (Wrapper.java)
at ch.fidelisfactory.pluspoints.Core.Wrapper.a (Wrapper.java:9)
at ch.fidelisfactory.pluspoints.Model.Exam.a (Exam.java:46)
at ch.fidelisfactory.pluspoints.SubjectActivity.i (SubjectActivity.java:9)
at ch.fidelisfactory.pluspoints.SubjectActivity.onCreate (SubjectActivity.java:213)
at android.app.Activity.performCreate (Activity.java:7136)
at android.app.Activity.performCreate (Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1272)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2908)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3063)
at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1823)
at android.os.Handler.dispatchMessage (Handler.java:107)
at android.os.Looper.loop (Looper.java:198)
at android.app.ActivityThread.main (ActivityThread.java:6729)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:876)
Run Code Online (Sandbox Code Playgroud)

Wrapper.java …

java java-native-interface android unsatisfiedlinkerror android-app-bundle

23
推荐指数
1
解决办法
443
查看次数