As in Java 9 some native APIs were removed for being deprecated, I didn't manage to find alternative solutions to replace them. I am a C++ developer, with little experience in java. The native APIs that I am using are: JVM_LoadClass0
, JVM_AllocateNewObject
and JVM_AllocateNewArray
.
My source code in Java is:
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 just 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 the other APIs.
Can someone suggest an alternative to this approach?
I’ve looked up 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 additional currClass
parameter can only guessed from the actual code, but apparently “the most recent class on the stack” is only used if currClass
is not null
, otherwise the loader of currClass
is used.
This raises some questions about the intention of the resolveClass
method.
In a normal environment, a custom class like your MercObjectInputStream
should not be loaded by the bootstrap loader, hence, the most recent class on the stack with a non-null classloader should be your own MercObjectInputStream
class. Using your own class’ loader for resolving a class is quiet easy, you can simply call Class.forName(name)
.
You are probing Thread.currentThread().getContextClassLoader()
which defaults to ClassLoader.getSystemClassLoader()
and is rarely set to null
. So the behavior of probing the classes on stack seems to be a rare corner case anyway.
When the context loader is not null
, you are not using it to load the class, but rather do loader.loadClass(scriptClassname); return loadClass0(scriptCls,name);
, loading a scriptClassname
first and use the result’s loader to resolve name
. If that’s intentional, you can use Class<?> scriptCls = loader.loadClass(scriptClassname); return Class.forName(name, true, scriptCls.getClassLoader());
to achieve the same without native methods.
You can do exactly the same as the original 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 should first rethink what the method actually is supposed to do.
This doc page at oracle.com contains complete list of JNI functions that are available in Java 9.
By looking at the old JNI functions you mentioned, I guess you may be particularly interested in:
DefineClass()
, FindClass()
, ...)AllocObject()
, NewObject()
, ...)NewObjectArray()
, GetArrayLength()
, ...)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With