使用本机API的替代解决方案:JVM_LOADCLASS0,JVM_ALLOCATENEWARRAY和JVM_ALLOC
Alternative solutions for using native APIs: JVM_LoadClass0, JVM_AllocateNewArray and JVM_AllocateNewObject
如Java 9中的9个本机API被删除而被删除,我没有设法找到替代它们的替代解决方案。我是C 开发人员,在Java方面几乎没有经验。我使用的本机API是:JVM_LoadClass0
,JVM_AllocateNewObject
和JVM_AllocateNewArray
。
我在Java中的源代码是:
protected Class resolveClass(MercObjectStreamClass v) throws IOException, ClassNotFoundException
{
/* Resolve by looking up the stack for a non-zero class
* loader. If not found use the system loader.
*/
String name = v.getName();
try
{
//we are using the loadClass0 method which calls the native JVM_LoadClass0
//JVM_LoadClass0 is deprecated and we need to replace the call
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if(loader == null) {
return loadClass0(null,name);
}
Class scriptCls = loader.loadClass(scriptClassname);
return loadClass0(scriptCls,name);
}
catch (ClassNotFoundException ex)
{
Class cl = (Class)primClasses.get(name);
if (cl != null)
return cl;
else
throw ex;
}
}
private native Class loadClass0(Class cl, String classname) throws ClassNotFoundException;
然后,本机代码只是一个简单的调用JVM_LOADCLASS0:
JNIEXPORT jclass JNICALL
Java_mercio_MercObjectInputStream_loadClass0(JNIEnv * env,
jobject this,
jclass curClass,
jstring currClassName)
{
return JVM_LoadClass0(env, this, curClass, currClassName);
}
本地部分与其他API相似。
有人可以建议这种方法的替代方案吗?
我已经查找了JVM_LoadClass0
的源代码,并找到了以下注释
// Load a class relative to the most recent class on the stack with a non-null
// classloader.
// This function has been deprecated and should not be considered part of the
// specified JVM interface.
附加currClass
参数的目的只能从实际代码中猜出,但是显然,只有当currClass
不是null
时,才使用"堆栈上的最新类",否则使用currClass
的加载程序。
这提出了有关resolveClass
方法的意图的一些问题。
在普通环境中,bootstrap加载器不应加载像您的
MercObjectInputStream
这样的自定义类,因此,使用非Null Classloader堆栈上的最新类应该是您自己的MercObjectInputStream
类。使用自己的班级加载程序来解决课程很安静,您只需致电Class.forName(name)
。您正在探测默认为
ClassLoader.getSystemClassLoader()
的Thread.currentThread().getContextClassLoader()
,很少设置为null
。因此,无论如何,在堆栈上探测类的行为似乎是一个罕见的角色。当上下文加载程序不是
null
时,您不是使用它来加载类,而是使用loader.loadClass(scriptClassname); return loadClass0(scriptCls,name);
,首先加载scriptClassname
并使用结果的加载程序来解决name
。如果是故意的,则可以使用Class<?> scriptCls = loader.loadClass(scriptClassname); return Class.forName(name, true, scriptCls.getClassLoader());
实现相同的情况。
您可以使用本机代码
中的Java 9中的原始代码完全相同protected Class resolveClass(MercObjectStreamClass v)
throws IOException, ClassNotFoundException
{
String name = v.getName();
try
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if(loader != null)
loader = loader.loadClass(scriptClassname).getClassLoader();
else
loader = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk(s -> s.map(sf -> sf.getDeclaringClass().getClassLoader())
.filter(Objects::nonNull)
.findFirst().orElse(null));
return Class.forName(name, true, loader);
}
catch (ClassNotFoundException ex)
{
Class cl = (Class)primClasses.get(name);
if (cl != null)
return cl;
else
throw ex;
}
}
,但是,如所说,您应该首先重新考虑该方法实际应该做什么。
oracle.com上的此文档页面包含JNI功能的完整列表。
通过查看您提到的旧JNI功能,我想您可能对:
特别感兴趣:- 类操作(
DefineClass()
,FindClass()
,...( - 对象操作(
AllocObject()
,NewObject()
,...( - 数组操作(
NewObjectArray()
,GetArrayLength()
,...(
- JVM 如何执行 JNI
- 正在从jvm.dll获取FindClass函数指针
- 设置 JVM 通过 JNI 初始化时创建的线程数
- 我能否通过 JNI 调试在本机代码中创建的 JVM?
- 如何在C++(JNI)中设置正在运行的JVM的类路径
- JVM 在从C++使用 JNI 时找不到类
- jvm.dll 上的加载库失败,错误代码为 183
- 在 UWP C++应用程序中生成 JVM 时崩溃
- 加载共享库时出错:JVM.dll
- 注入 jar 并替换正在运行的 JVM 中的类
- JVM 在 WindowAccessbridge 中崩溃
- 在尝试访问 DLL 函数时从 JVM 获取EXCEPTION_ACCESS_VIOLATION
- C 在运行的JVM中调用功能
- 为什么要在JNI内部调用纤维在JVM中抛出堆叠量
- 为Android上的MediaStreamer2控制台应用提供JVM
- JVM在libjvm.so中经常因Sigsegv Java致命错误而崩溃
- JVM调用时可以找到Linux插座API
- GCC和JVM自动平行批次
- Opencv JNA&C++ FaceRecognizer 导致 JVM 崩溃
- c++中的JNI JVM无法使用分配的堆内存