标签: jnienv

保持对JNIEnv环境的全局引用

JNIEnv在全局存储,所以我稍后可以调用静态java方法.但是存储一个全局指针是否是必要的JNIEnv,它们可以与任何其他java对象一起存储,或者它是一个不需要它的特殊情况.

JNIEnv* globalEnvPointer;

[JNICALL etc] void init(JNIENv* env, [etc])
{
   //required?
   globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
   //or is this OK?
   globalEnvPointer = env;
}
Run Code Online (Sandbox Code Playgroud)

编辑

我在这里有点愚蠢,将使用的所有方法globalEnvPointer都在我的init中调用,因为我init实际上是我的c程序main方法,直到程序结束才会返回.我也在c程序中没有使用其他线程.我认为这简化了答案.

JNIEnv* globalEnvPointer;

[JNICALL etc] void main(JNIENv* env, [etc])
{
   //required?
   globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
   //or is this OK?
   globalEnvPointer = env;
   someMethod();
}

void someMethod()
{
   //use globalEnvPointer here
}
Run Code Online (Sandbox Code Playgroud)

c java-native-interface jnienv

36
推荐指数
1
解决办法
1万
查看次数

JNI_CreateJavaVM()以退出代码1终止

我正在尝试使用JNI从C++调用Java方法.要做到这一点,我已经安装jdk1.7.0_51,链接jdk1.7.0_51\lib\jvm.lib,包括jdk1.7.0_51\includejdk1.7.0_51\include\win32.在Visual Studio 2012中使用以下代码我尝试创建一个Java vm对象 - 但该函数总是以退出代码1终止我的应用程序(该函数不返回1:我的程序完全终止并发送退出代码1).

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

int main(int argc, char*argv[]){
  JNIEnv* env = nullptr;
  JavaVM* jvm = nullptr;
  JavaVMInitArgs vm_args;
  JavaVMOption options[2];
  options[0].optionString = "-Djava.class.path=.";
  options[1].optionString = "-DXcheck:jni:pedantic";  
  vm_args.version = JNI_VERSION_1_6;
  vm_args.nOptions = 2;
  vm_args.options = options;
  vm_args.ignoreUnrecognized = JNI_TRUE; // remove unrecognized options
  int ret = JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);
  std::cout << "This code is never reached" << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

操作系统: Windows 7(x64)

编译器: Visual …

c++ java-native-interface jnienv

7
推荐指数
1
解决办法
1549
查看次数

Xamarin.Android绑定调用java Object方法

我通过名为Xamarin.GradleBinding的visual studio扩展创建了java绑定库.我添加了ru.rambler.android:swipe-layout:1.0.14包,并在使用它时SwipeLayout,一切正常.但不幸的是,它没有创建相应的C#类或类似的东西.我尝试手动添加包但仍然没有.

我检查了GitHub上源代码.SwipeLayout有一个没有参数的public void方法reset():

public void reset()
Run Code Online (Sandbox Code Playgroud)

我尝试从c#中调用此方法JNIEnv.

IntPtr type = JNIEnv.FindClass("ru/rambler/libs/swipe_layout/SwipeLayout");
IntPtr method = JNIEnv.GetMethodID(type, "reset", "()V");
try
{
    JNIEnv.CallObjectMethod(_swiper.Handle, method);
}
catch (Exception ex)
{
    var s = ex.Message;
}
Run Code Online (Sandbox Code Playgroud)

已成功找到类型和方法,但正在调用

JNIEnv.CallObjectMethod(_swiper.Handle, method);
Run Code Online (Sandbox Code Playgroud)

这个方法崩溃了应用程序,它甚至没有进入catch块.

Tt必须是_swiper.Handle第一个参数的原因. _swiper字段是类型,ViewGroup因为SwipeLayout派生自ViewGroup.我找不到如何获取视图的指针来传递该方法.

在调试时,当我调查时_swiper,它似乎是正确的实例SwipeLayout

在此输入图像描述

java xamarin.android xamarin jnienv java-binding

6
推荐指数
1
解决办法
229
查看次数

JNI - 有没有办法让 JVM 调用 JNI_OnUnload ?

关于这方面的信息很少,例如2006 年的这个人们放弃了优雅地释放 JNI 资源。

JNI_OnUnload( Oracle 文档) 旨在当 JVM 中不再需要您的本机功能时释放资源(特别是“全局引用”)。本机库将像这样加载

static {
    System.loadLibrary("mylibjni"); // on Linux this translates to "libmylibjni.so"
}
Run Code Online (Sandbox Code Playgroud)

...但是 Java 没有提供明确的卸载方法。

发生了什么:在我的 lib 中,由于没有机会进行清理,lib 最终确实卸载了(我不明白什么时候,请参阅下面的调用堆栈),但是为时已晚,这会触发一些拥有 JNI 全局引用的全局变量调用DeleteGlobalRef失败:

# JRE version: OpenJDK Runtime Environment (10.0.2+13) (build 10.0.2+13)
# Java VM: OpenJDK 64-Bit Server VM (10.0.2+13, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C  [libblahjni.so+0x9a7e6]  JNIEnv_::DeleteGlobalRef(_jobject*)+0x14
Run Code Online (Sandbox Code Playgroud)

深入研究一下,这是因为线程上没有JNIEnv执行卸载(我正在缓存环境thread_local)。当时尝试检索 Env 没有成功 …

c++ java java-native-interface shared-libraries jnienv

6
推荐指数
0
解决办法
1150
查看次数

带有 JNI 的 C++ 应用程序抛出错误“找不到 jvm.dll。重新安装应用程序可以修复......”

我在 VC6 中编写了一个普通的 C++ 应用程序,它使用 jni 调用 java 中的方法。为此,我在项目目录中包含了 jni.h 和其他 lib 文件夹。

代码编译但是当我运行应用程序时它失败说“找不到jvm.dll。重新安装应用程序会修复它”。但是 jvm.dll 存在于我的电脑中。

如果我将应用程序的工作目录设置为 jvm.dll 所在的位置,那么它就像一个魅力。我无法将应用程序的工作目录设置为 jvm.dll 目录,因为该应用程序将来会成为 dll。

我也尝试将系统变量中的 PATH 变量更新到 jvm.dll 的位置,但没有任何效果..

我怀疑 jvm.lib 正在从我的应用程序未提供的某个目录位置加载 jvm.dll .. 因此它失败了,..

请建议我出了什么问题。

提前致谢。

问候拉加文德拉

java-native-interface jniwrapper jnienv

5
推荐指数
1
解决办法
2389
查看次数

JNI 在应用程序中检测到错误:CallObjectMethodV 的返回类型与 void android.media.AudioTrack.play() 不匹配

我正在尝试使用 AudioTrack 从 JNI 播放音频缓冲区

使用以下代码从 JNI 初始化 AudioTrack 对象

    jclass AudioTrack = mEnv->FindClass("android/media/AudioTrack");
    jclass AudioFormat = mEnv->FindClass("android/media/AudioFormat");
    jclass AudioManager = mEnv->FindClass("android/media/AudioManager");

    jfieldID AudioFormat_ENCODING_PCM_16BIT = mEnv->GetStaticFieldID(AudioFormat, "ENCODING_PCM_16BIT", "I");
    jint ENCODING_PCM_16BIT =mEnv->GetStaticIntField( AudioFormat, AudioFormat_ENCODING_PCM_16BIT);

    jfieldID AudioFormat_CHANNEL_CONFIGURATION_MONO = mEnv->GetStaticFieldID(AudioFormat, "CHANNEL_CONFIGURATION_MONO", "I");
    jint CHANNEL_CONFIGURATION_MONO =mEnv->GetStaticIntField( AudioFormat, AudioFormat_CHANNEL_CONFIGURATION_MONO);

    getMinBufferSize = mEnv->GetStaticMethodID(AudioTrack,"getMinBufferSize","(III)I");

    // int minBufferSize = AudioTrack.getMinBufferSize(8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AdioFormat.ENCODING_PCM_16BIT);
    minBufferSize = mEnv->CallStaticIntMethod(AudioTrack,getMinBufferSize,8000,ENCODING_PCM_16BIT,CHANNEL_CONFIGURATION_MONO);

    //AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT, minBufferSize,AudioTrack.MODE_STREAM);
    jfieldID AudioManager_STREAM_MUSIC = mEnv->GetStaticFieldID(AudioManager, "STREAM_MUSIC", "I");
    jint STREAM_MUSIC = mEnv->GetStaticIntField( AudioManager, AudioManager_STREAM_MUSIC);

    jfieldID AudioTrack_MODE_STREAM = mEnv->GetStaticFieldID(AudioTrack, "MODE_STREAM", …
Run Code Online (Sandbox Code Playgroud)

java java-native-interface android android-ndk jnienv

5
推荐指数
1
解决办法
3094
查看次数

从 C 调用 Java 方法而不从 C 启动 JVM

我正在寻找有关如何使用 JNI 从 C 调用 Java 方法的教程。在我迄今为止找到的所有教程中,示例展示了如何首先从 C 创建 JVM。

我的应用程序从Java开始并使用JNI调用一些C函数。我现在需要从 C 调用一些 Java 函数,但我不想从 C 启动 JVM。

例如,是否可以创建一个用 C 实现的“本机”方法,并使用它来保存指针JNIEnv,然后重用它,而不是从 C 创建一个新的 JVM 实例来调用 Java方法?

有例子吗?


编辑:

看过这篇文章的人一定要小心!仅使用JNIEnv*来自当前 JNI 调用的实例!JNIEnv*如果您不想让程序崩溃,请不要保存和重用之前获得的任何指针。

在最好的情况下,使用旧的保存的指针可能会使您的应用程序崩溃。在更糟糕的情况下,它可能会导致难以调试和理解的低级不一致问题

不应缓存任何JNIEnv*实例,因为如果您的程序从 Java 启动,那么您的 C 代码无论如何都只能作为本机 java 方法执行,其 C 实现始终会获取相关的JNIEnv*实例。这是在本机方法返回之前应使用的唯一实例,而不是任何旧的已保存实例。

c java java-native-interface jnienv

5
推荐指数
1
解决办法
2176
查看次数

如何使用 JNI_CreateJavaVM 运行模块化 java 应用程序

我将我们的本机 Windows 应用程序启动器从 Java 8 移植到 Java 11。我们过去常常调用JNI_CreateJavaVM方法来实例化 JVM 实例、查找主类并调用其main方法。对于模块化应用程序,env->FindClass不会返回我们的应用程序类。我尝试调用Class.forName,但它也没有返回类实例。

另外,还有JNI_CreateJavaVM对争论的抱怨--add-modules

我们应该如何指定 JNI api 加载的模块?

我该怎么做才能从本机部分找到应用程序类?

java java-native-interface java-platform-module-system jnienv java-11

5
推荐指数
1
解决办法
395
查看次数

Android JNI 错误:NoSuchMethodError:没有非静态方法

我正在尝试做的简化如下。

  1. Java -> 调用 C++ 函数 A
  2. C++ 函数 A 调用 C++ 函数 B
  3. C++ 函数 B 调用 Java 方法 C

我必须存储 JVM(2) 和 global jobject(3)。

但在第 3 部分,

JNI DETECTED ERROR IN APPLICATION: JNI CallVoidMethodV called with pending exception java.lang.NoSuchMethodError: no non-static method "Lpackage/name/here/d/b;.setInput([F)V"
Run Code Online (Sandbox Code Playgroud)

我总是收到这个错误。


代码

结构

  • 包装器
  • 本机-lib.cpp
  • 包装器.cpp

** <-> 表示沟通

其他 Java 类 <-> Wrapper.java

Wrapper.java <-> native-lib.cpp

native-lib.cpp <-> Wrapper.cpp

Wrapper.cpp <-> 其他 C++ 类


包装器

private static long wrapperAddr = 0; // initializes later …
Run Code Online (Sandbox Code Playgroud)

c++ java java-native-interface android jnienv

5
推荐指数
1
解决办法
2797
查看次数

如何使用 JNI 从已运行的 JVM 获取 JavaVM 或 JNIEnv?

我正在做一个涉及 Rust 和 Java 的项目。我需要能够从 Rust 端使用 JNI,而无需 Java 端调用它(因为它不是我的代码)。到目前为止,我已经能够确保我的 DLL 被注入(在按键上打开一个小窗口,我一直在使用它进行调试)。

相关代码的简短示例如下:

use jni::sys::{JNI_GetCreatedJavaVMs, JNIInvokeInterface_};


let jvm_ptr = null_mut() as *mut *mut *const JNIInvokeInterface_;
let count = null_mut();

// hasn't crashed

JNI_GetCreatedJavaVMs(jvm_ptr, 1, count);  // https://docs.rs/jni/latest/jni/sys/fn.JNI_GetCreatedJavaVMs.html

// crashes
Run Code Online (Sandbox Code Playgroud)

我的问题是:在这种情况下是否有可能/如何获得 JNI 环境?

java-native-interface ffi dll-injection rust jnienv

5
推荐指数
1
解决办法
857
查看次数