Так как в 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.
Может кто-нибудь предложить альтернативу этому подходу?
Я посмотрел исходный код 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;
}
}
но, как уже было сказано, вы должны сначала переосмыслить, что на самом деле должен делать метод.
Эта страница документа на oracle.com содержит полный список функций JNI, доступных в Java 9
Рассматривая старые функции JNI, о которых вы упомянули, я думаю, что вас могут особенно заинтересовать:
DefineClass()
, FindClass()
…)AllocObject()
, NewObject()
…)NewObjectArray()
, GetArrayLength()
…)