使用本机API的替代解决方案:JVM_LOADCLASS0,JVM_ALLOCATENEWARRAY和JVM_ALLOC

Alternative solutions for using native APIs: JVM_LoadClass0, JVM_AllocateNewArray and JVM_AllocateNewObject

本文关键字:JVM LOADCLASS0 ALLOCATENEWARRAY ALLOC 解决方案 本机 API      更新时间:2023-10-16

如Java 9中的9个本机API被删除而被删除,我没有设法找到替代它们的替代解决方案。我是C 开发人员,在Java方面几乎没有经验。我使用的本机API是:JVM_LoadClass0JVM_AllocateNewObjectJVM_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(),...(