Альтернативные решения для использования собственных API: JVM_LoadClass0, JVM_AllocateNewArray и JVM_AllocateNewObject

Так как в Java 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.

Может кто-нибудь предложить альтернативу этому подходу?

7

Решение

Я посмотрел исходный код 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 метод.

  • В обычной среде пользовательский класс, такой как ваш MercObjectInputStream не должен загружаться загрузчиком начальной загрузки, следовательно, самый последний класс в стеке с ненулевым загрузчиком классов должен быть вашим собственным MercObjectInputStream учебный класс. Использование вашего собственного загрузчика класса для разрешения класса очень просто, вы можете просто позвонить Class.forName(name),

  • Вы прощупываете Thread.currentThread().getContextClassLoader() который по умолчанию ClassLoader.getSystemClassLoader() и редко устанавливается на 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;
}
}

но, как уже было сказано, вы должны сначала переосмыслить, что на самом деле должен делать метод.

4

Другие решения

Эта страница документа на oracle.com содержит полный список функций JNI, доступных в Java 9

Рассматривая старые функции JNI, о которых вы упомянули, я думаю, что вас могут особенно заинтересовать:

3

По вопросам рекламы [email protected]