gpt4 book ai didi

java - JNI RegisterNatives 不适用于 ClassLoader.loadClass() 加载的类

转载 作者:行者123 更新时间:2023-11-29 05:49:56 25 4
gpt4 key购买 nike

我要在现有的 C++ 应用程序中嵌入 JVM,并且需要使用类注册 native Java 函数的实现。

考虑这个带有原生函数的简单类:

class Native {
static {
System.out.println("Class 'Native' static initializer called.");
}

public native int f(int i);
}

在 JVM 中,我正在运行 OSGi,这就是我需要使用 Java 代码(使用正确的类加载器)获取类而不是从 JNI 加载它们的原因。但是,为了使这个示例简单,我省略了 OSGi。

我有这四种不同的 Java 方法来获取 jclass C++ 中的值:

class Bridge {
public Class<?> getNativeClass1() throws ClassNotFoundException {
return getClass().getClassLoader().loadClass("org.example.Native");
}

public Class<?> getNativeClass2() throws ClassNotFoundException {
return Class.forName("org.example.Native", false, getClass().getClassLoader());
}

public Class<?> getNativeClass3() throws ClassNotFoundException {
final Class<?> clazz = getClass().getClassLoader()
.loadClass("org.example.Native");
clazz.getMethods();
return clazz;
}

public Class<?> getNativeClass4() throws ClassNotFoundException {
return Class.forName("org.example.Native", true, getClass().getClassLoader());
}
}

在 C++ 中为 Native.f() 注册 native 函数实现我打电话:

JNIEnv* env = ...
jclass clazz = ...; // Calling one of the four methods above.
JNINativeMethod nativeMethod = {
(char*) "f", // Method name 'f'.
(char*) "(I)I;", // Signature 'int --> int'.
(void*) f // Pointer to C++ implementation of function.
};
env->RegisterNatives(clazz, &nativeMethod, 1);

取决于我使用哪种方法获取 Class<?>例如,我得到不同的结果:

  • getNativeClass1() : 静态初始值设定项未在类中执行 Native在加载类时(但当然是在创建类的实例时)和 native 实现正确绑定(bind)。 (在 Java 中调用 native 函数会产生不正确的结果或导致 JVM 崩溃。)
  • getNativeClass2() : 同上。
  • getNativeClass3() : 类中仍未调用静态初始值设定项 Native当类已加载但 native 实现 正确绑定(bind)时,我可以调用 f()成功。
  • getNativeClass3() : 在类 Native 中调用了静态初始化程序当加载类并且 native 实现正确绑定(bind)时。

看来 ClassLoader.loadClass()以某种方式加载类,因此它未正确初始化并且 JNIEnv::RegisterNatives()将无法正常工作。但是,调用 Class.getMethods()将以某种方式初始化类(不调用静态初始化程序),以便绑定(bind)本地方法。

另一方面,Class.forName(clazz, false, classLoader)似乎与 Class.loadClass() 完全一样返回一个未初始化的 Class实例。

谁能解释一下

  1. 一个未初始化的类,如 getNativeClass1() 返回的类和 getNativeClass2()
  2. 一个部分初始化的类,如 getNativeClass3() 返回的类
  3. 一个像getNativeClass4()返回的完全初始化的类

在调用 JNIEnv::RegisterNatives() 之前加载类的最便携方式是什么? ?

最佳答案

So it seems that ClassLoader.loadClass() loads the class in a way so it is not properly initialized

根据documentation :

loadClass(String):“调用此方法等同于调用 loadClass(name, false)。”

loadClass(String,boolean)(强调已添加):“如果使用上述步骤找到类,并且解析标志为真,则此方法将在生成的 Class 对象上调用 resolveClass(Class) 方法”

这两个方法旨在供需要在加载和链接之间执行某些操作的类加载器内部使用。我不确定为什么 loadClass(String) 被标记为公开,但可以说不应该。

and what is the most portable way to load a class before calling

Class.forName(),它使用上下文类加载器并确保该类已准备就绪。

关于java - JNI RegisterNatives 不适用于 ClassLoader.loadClass() 加载的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14319314/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com