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

As in Java 9, some native APIs were removed for obsolescence, I could not find alternative solutions to replace them. I am a C ++ developer, with little experience in Java. The native APIs I use are: JVM_LoadClass0 , JVM_AllocateNewObject and JVM_AllocateNewArray .

My Java source code:

 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; 

And then the native code is a simple call to JVM_LoadClass0:

 JNIEXPORT jclass JNICALL Java_mercio_MercObjectInputStream_loadClass0(JNIEnv * env, jobject this, jclass curClass, jstring currClassName) { return JVM_LoadClass0(env, this, curClass, currClassName); } 

The native part is similar to other APIs.

Can anyone suggest an alternative to this approach?

+7
java c ++ c jvm java-9
source share
2 answers

Ive looked at the source code of JVM_LoadClass0 and found the following comment

 // 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. 

The purpose of the currClass optional parameter can only be guessed from the actual code, but apparently the "most recent class on the stack" is used only if currClass not null , otherwise the currClass loader.

This raises some questions about the intent of the resolveClass method.

  • In a normal environment, a custom class, such as your MercObjectInputStream , should not be loaded by the boot loader, so the very last class on the stack with a nonzero class loader should be your own MercObjectInputStream class. Using your own class loader to resolve the class is very simple, you can just call Class.forName(name) .

  • You examine Thread.currentThread().getContextClassLoader() , which defaults to ClassLoader.getSystemClassLoader() and is rarely set to null . Thus, the behavior of probing classes on the stack is apparently a rare cornerstone.

  • When the context loader is not null , you do not use it to load the class, but rather do loader.loadClass(scriptClassname); return loadClass0(scriptCls,name); loader.loadClass(scriptClassname); return loadClass0(scriptCls,name); , first load scriptClassname and use the results loader to resolve name . If this is intentional, you can use Class<?> scriptCls = loader.loadClass(scriptClassname); return Class.forName(name, true, scriptCls.getClassLoader()); Class<?> scriptCls = loader.loadClass(scriptClassname); return Class.forName(name, true, scriptCls.getClassLoader()); to achieve the same without their own methods.

You can do the same as the source code in Java 9 without native code using

 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; } } 

but as said, you must first rethink what this method should do.

+4
source share

This page of the document at oracle.com contains a complete list of JNI functions available in Java 9.

Looking at the old JNI features you mentioned, I think you might be particularly interested in:

+3
source share

All Articles