diff --git a/README-RU.md b/README-RU.md new file mode 100644 index 000000000..0e658d12f --- /dev/null +++ b/README-RU.md @@ -0,0 +1,122 @@ +[English](README.md) + +# Zote Core Loader + +__Zote Core__ — серверное ядро, основанное на Inner Core 1.16.200, созданное для создания уникального геймплея с модами. + +Основой серверного ядра послужил [Nukkit-MOT](https://github.com/MemoriesOfTime/Nukkit-MOT), его можно легко обновить, заменив соответствующую библиотеку. + +![Zote Core](/.github/logo.png) + +## Установка + +Поддерживается любая платформа, поддерживающая Java 17 или выше. Загрузите последний релиз серверного ядра, либо соберите репозиторий с помощью Gradle. + +Запустите собранное ядро, открыв консоль в папке с ним: + +```sh +java -jar ZoteCore-SNAPSHOT.jar -XX:MaxRAMPercentage=95.0 +``` + +## Конфигурация + +Настройки производятся посредством двух основных файлов: *server.properties* и *zotecore.yml*. Они будут созданы автоматически сразу же после запуска ядра, документация по первому доступна в репозитории Nukkit-MOT. + +Некоторые настройки Nukkit заблокированы загрузчиком, среди которых *multiversion-min/max-protocol* (422), *xbox-auth* (авторизация с помощью него не доступна) и *save-player-data-by-uuid* (false). + +Чтобы сокеты клиентов отваливались, не крашая сервер, отключите Watchdog. В текущей реализации альтернативные варианты исправления недоступны, необходимая настройка `thread-watchdog=on`. + +### zotecore.yml + +Стандартные настройки ядра, которые можно использовать как основу: + +```yml zotecore.yml +# Изменение информации пака, который клиент должен иметь для входа на сервер. +# Устаревшие или не реализованные методы, однако, добавлены не будут. +pack: Inner Core Test +pack-version: 2.3.0b115 test +pack-version-code: 152 + +# Устанавливает список модов и конфигураций для загрузки, вы можете +# указать название, имя папки модпака из /modpacks или путь. +modpack: innercore + +# Использование ванильного интерфейса верстака, вместо кастомного. +# Внимание: в настоящее время не рекомендуется использовать, +# так как некоторые рецепты отображаются с проблемами. +use-legacy-workbench-override: on + +# Отключение исправления инвентаря для подключенных клиентов, +# устаревшие версии не работают должным образом с ним, +# не позволяя перемещать предметы по инвентарю. +use-legacy-inventory: on + +# Переключение режима отладки для неподдерживаемых методов (например, клиентских). +# Может быть одним из: none, debug (по умолчанию), warning, raise. +unsupported-method-handling: debug + +# Могут ли моды использовать небезопасные функции (например, вызов eval) или нет. +# Внимание: это может создать риск безопасности, однако, например, его запрет +# влияет на requireGlobal и часто может нарушить работу модов. +allow-unsafe-scripting: on + +# Режим разработчика позволяет получать дополнительную информацию +# о работе ядра, а также профайлинг методов. +developer-mode: off + +# Время в секундах между запусками автосохранения данных модов (любое от 20), +# а также мира, если он включен в другой опции. +auto-save-period: 60 + +# Нужно ли помимо данных модов сохранять еще и миры. +auto-save-world: on + +# Включен ли сокетный сервер или нет. Сокеты требуют дополнительный порт, +# подключение через серверные сокеты более нестабильное. +socket-server-enable: on + +# Порт серверного сокета, обычно должен быть между 10000 и 24999. +# Но учтите, что по умолчанию клиент использует порт 2304. +socket-port: 2304 + +# Отправляет текстовую форму игрокам когда происходят ошибки тика, +# содержит только стактрейс скрипта (без потенциально опасных свойств). +display-ticking-errors-to-players: true + +# Если серверный тик прерывается слишком часто, сервер будет остановлен; +# в противном случае тик будет пытаться продолжать перезапуски. +stop-on-critical-ticking-error: false + +# Максималльное количесво пакетов которые может хранить сервер для отправки игроку +# Если количесвто пакетов привышает это, то игрок кикается с сервера +max-packet-sending: 200 + +# Дополнительная информация в лог +# debug-logger: on +# info-logger: on +``` + +## Консольные команды + ++ custom_items — выводит список кастумных предметов ++ custom_blocks — выводит список кастумных блоков ++ mods — выводит список модификаций на сервере ++ inner_core_network — выводит список подключенных к протоколу игроков на сервере ++ state — выводит стейты блока по рантайм идентификатору ++ profilecallback [enabled] [showParameters] — отладка и профайлинг калбеков ++ dimensions_list - выводит список измерений + +> Все команды предназначены для операторов и не могут быть вызваны игроками. + +## Лицензия + +![Licensing](/.github/license.jpg) + +## Техническая информация + +| Ключ | Значение | +|---|---| +| Версия протокола | 422 (1.16.200) | +| Коммит Apparatus | `73194cfd` | +| Коммит Instant Referrer | `a264591` | +| Коммит Nukkit-MOT | `191f6ea2b29c083d41470125fd6cd1fb3d698399` | diff --git a/README.md b/README.md index 4a9fe2261..47279e885 100644 --- a/README.md +++ b/README.md @@ -1,120 +1,116 @@ +[Russian](README-RU.md) + # Zote Core Loader -__Zote Core__ — серверное ядро, основанное на Inner Core 1.16.200, созданное для создания уникального геймплея с модами. +__Zote Core__ — A server core based on Inner Core 1.16.200, designed to create a unique gameplay with mods. -Основой серверного ядра послужил [Nukkit-MOT](https://github.com/MemoriesOfTime/Nukkit-MOT), его можно легко обновить, заменив соответствующую библиотеку. +The server core is based on [Nukkit-MOT](https://github.com/MemoriesOfTime/Nukkit-MOT ), it can be easily updated by replacing the corresponding library. ![Zote Core](/.github/logo.png) -## Установка +## Installation -Поддерживается любая платформа, поддерживающая Java 17 или выше. Загрузите последний релиз серверного ядра, либо соберите репозиторий с помощью Gradle. +Any platform supporting Java 17 or higher is supported. Download the latest release of the server core, or build a repository using Gradle. -Запустите собранное ядро, открыв консоль в папке с ним: +Run the assembled kernel by opening the console in the folder with it: ```sh -java -jar ZoteCore-SNAPSHOT.jar -XX:MaxRAMPercentage=95.0 --add-opens java.base/jdk.internal.loader=ALL-UNNAMED +java -jar ZoteCore-SNAPSHOT.jar ``` -## Конфигурация +## Configuration -Настройки производятся посредством двух основных файлов: *server.properties* и *zotecore.yml*. Они будут созданы автоматически сразу же после запуска ядра, документация по первому доступна в репозитории Nukkit-MOT. +The settings are made using two main files: *server.properties* and *zotecore.yml*. They will be created automatically immediately after the kernel is launched, the documentation for the first one is available in the Nukkit-MOT repository. -Некоторые настройки Nukkit заблокированы загрузчиком, среди которых *multiversion-min/max-protocol* (422), *xbox-auth* (авторизация с помощью него не доступна) и *save-player-data-by-uuid* (false). +Some settings of Nukkit are blocked by the loader, including *multiversion-min/max-protocol* (422), *xbox-auth* (authorization using it is not available) and *save-player-data-by-uuid* (false). -Чтобы сокеты клиентов отваливались, не крашая сервер, отключите Watchdog. В текущей реализации альтернативные варианты исправления недоступны, необходимая настройка `thread-watchdog=on`. +To make client sockets fall off without crashing the server, disable Watchdog. In the current implementation, alternative fix options are not available, the necessary setting is `thread-watchdog=on'. ### zotecore.yml -Стандартные настройки ядра, которые можно использовать как основу: +Standard kernel settings that can be used as a basis: ```yml zotecore.yml -# Изменение информации пака, который клиент должен иметь для входа на сервер. -# Устаревшие или не реализованные методы, однако, добавлены не будут. +# Change resolution of pack that client should have to log into server. +# However, no deprecated or unimplemented methods will be added. pack: Inner Core Test -pack-version: 2.3.0b115 test -pack-version-code: 152 +pack-version: 2.3.0b119 +pack-version-code: 159 -# Устанавливает список модов и конфигураций для загрузки, вы можете -# указать название, имя папки модпака из /modpacks или путь. -modpack: innercore +# Sets the list of mods and configs to load, you can specify +# name, folder name of a modpack from /modpacks or a path. +# modpack: StoneBlock -# Использование ванильного интерфейса верстака, вместо кастомного. -# Внимание: в настоящее время не рекомендуется использовать, -# так как некоторые рецепты отображаются с проблемами. -use-legacy-workbench-override: on +# Use vanilla crafting table interface, instead of custom one. +# Attention: currently not recommended and recipes dislayed with bugs. +# use-legacy-workbench-override: off -# Отключение исправления инвентаря для подключенных клиентов, -# устаревшие версии не работают должным образом с ним, -# не позволяя перемещать предметы по инвентарю. -use-legacy-inventory: on +# Disabling inventory fix for connected clients, outdated versions do not +# work properly with it, not allowing moving items around inventory. +# use-legacy-inventory: off -# Переключение режима отладки для неподдерживаемых методов (например, клиентских). -# Может быть одним из: none, debug (по умолчанию), warning, raise. -unsupported-method-handling: debug +# Switches the debugging mode for unsupported methods (e.g., client-side). +# Might be one of: none, debug (default), warning, raise. +# unsupported-method-handling: raise -# Могут ли моды использовать небезопасные функции (например, вызов eval) или нет. -# Внимание: это может создать риск безопасности, однако, например, его запрет -# влияет на requireGlobal и часто может нарушить работу модов. -allow-unsafe-scripting: on +# Can mods use unsafe features (e.g., calling eval) or not. +# Attention: can create a security risk, however, for example, +# using requireGlobal can often disrupt operation of mods. +# allow-unsafe-scripting: off -# Режим разработчика позволяет получать дополнительную информацию -# о работе ядра, а также профайлинг методов. -developer-mode: off +# Developer mode allows you to receive additional information +# about engine operation, as well as profiling of methods. +# developer-mode: on -# Время в секундах между запусками автосохранения данных модов (любое от 20), -# а также мира, если он включен в другой опции. -auto-save-period: 60 +# Time in seconds between auto-saving data of mods (any value above 20), +# as well as the world if it is included in another option. +# auto-save-period: 180 -# Нужно ли помимо данных модов сохранять еще и миры. -auto-save-world: on +# Whether to save worlds in addition to mod data. +# auto-save-world: off -# Включен ли сокетный сервер или нет. Сокеты требуют дополнительный порт, -# подключение через серверные сокеты более нестабильное. -socket-server-enable: on +# Whether socket server enabled or not. +# Server socket requires an additional port, connection +# through server sockets is more unstable. +# socket-server-enable: off -# Порт серверного сокета, обычно должен быть между 10000 и 24999. -# Но учтите, что по умолчанию клиент использует порт 2304. -socket-port: 2304 +# Server socket port, usually should be between 10000 and 24999. +# But keep in mind that the client uses port 2304 by default. +# socket-port: 19131 -# Отправляет текстовую форму игрокам когда происходят ошибки тика, -# содержит только стактрейс скрипта (без потенциально опасных свойств). -display-ticking-errors-to-players: true +# Sends form to players when ticking exception happens, +# contains only script stacktrace (without sensitive properties). +# display-ticking-errors-to-players: false -# Если серверный тик прерывается слишком часто, сервер будет остановлен; -# в противном случае тик будет пытаться продолжать перезапуски. -stop-on-critical-ticking-error: false +# If ticking callback interrupts too often, server will be stopped; +# otherwise it will continue trying restart itself continiously. +# stop-on-critical-ticking-error: true -# Максималльное количесво пакетов которые может хранить сервер для отправки игроку -# Если количесвто пакетов привышает это, то игрок кикается с сервера -max-packet-sending: 200 +# Maximum number of packets sent to the client +# max-packet-sending: 150 -# Дополнительная информация в лог +# Additional information in the log # debug-logger: on # info-logger: on ``` -## Консольные команды - -+ custom_items — выводит список кастумных предметов -+ custom_blocks — выводит список кастумных блоков -+ mods — выводит список модификаций на сервере -+ inner_core_network — выводит список подключенных к протоколу игроков на сервере -+ state — выводит стейты блока по рантайм идентификатору -+ profilecallback [enabled] [showParameters] — отладка и профайлинг калбеков -+ dimensions_list - выводит список измерений - -> Все команды предназначены для операторов и не могут быть вызваны игроками. +## Console commands -## Лицензия ++ custom_items — displays a list of custom items ++ custom_blocks — displays a list of custom blocks ++ mods — displays a list of modifications on the server ++ inner_core_network — displays a list of players connected to the protocol on the server ++ state — outputs block statuses by the runtime ID ++ profilecallback [enabled] [showParameters] — debugging and profiling of callbacks ++ dimensions_list - displays a list of dimensions -![Licensing](/.github/license.jpg) +> All commands are for operators and cannot be called by players. -## Техническая информация +## Technical information | Ключ | Значение | |---|---| -| Версия протокола | 422 (1.16.200) | -| Коммит Apparatus | `73194cfd` | -| Коммит Instant Referrer | `a264591` | -| Коммит Nukkit-MOT | `191f6ea2b29c083d41470125fd6cd1fb3d698399` | +| Protocol version | 422 (1.16.200) | +| Commit Apparatus | `73194cfd` | +| Commit Instant Referrer | `a264591` | +| Commit Nukkit-MOT | `191f6ea2b29c083d41470125fd6cd1fb3d698399` | diff --git a/build.gradle b/build.gradle index 14deb1880..3729d710d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ version 'SNAPSHOT' application { mainClass = 'com.reider745.Main' - applicationDefaultJvmArgs = ['--add-opens', 'java.base/jdk.internal.loader=ALL-UNNAMED'] + //applicationDefaultJvmArgs = ['--add-opens', 'java.base/jdk.internal.loader=ALL-UNNAMED'] } repositories { diff --git a/src/main/java/com/reider745/api/ReflectHelper.java b/src/main/java/com/reider745/api/ReflectHelper.java index 13c3be16d..c8921cf13 100644 --- a/src/main/java/com/reider745/api/ReflectHelper.java +++ b/src/main/java/com/reider745/api/ReflectHelper.java @@ -51,13 +51,25 @@ public static void setField(Class self, String name, Object v) { } } - public static void invokeVoid(Object self, String name, Object[] args, Class... classes){ + public static T invoke(Object self, String name, Object[] args, Class... classes){ try { Method method = self.getClass().getDeclaredMethod(name, classes); method.setAccessible(true); - method.invoke(self, args); + return (T) method.invoke(self, args); } catch (Exception e) { e.printStackTrace(); } + return null; + } + + public static T invoke(Class self, String name, Object[] args, Class... classes){ + try { + Method method = self.getDeclaredMethod(name, classes); + method.setAccessible(true); + return (T) method.invoke(null, args); + } catch (Exception e) { + e.printStackTrace(); + } + return null; } } diff --git a/src/main/java/com/reider745/event/EventListener.java b/src/main/java/com/reider745/event/EventListener.java index 355579b2e..68fcaa2e7 100644 --- a/src/main/java/com/reider745/event/EventListener.java +++ b/src/main/java/com/reider745/event/EventListener.java @@ -551,7 +551,7 @@ public void stopServer(ServerStopEvent event){ e.printStackTrace(); } } - + @EventHandler public void onItemDespawn(ItemDespawnEvent event){ if(!ItemMethod.canShouldDespawn(event.getEntity().getItem().getId())) diff --git a/src/main/java/com/reider745/hooks/LevelHooks.java b/src/main/java/com/reider745/hooks/LevelHooks.java index 59fcf4c52..121069e7e 100644 --- a/src/main/java/com/reider745/hooks/LevelHooks.java +++ b/src/main/java/com/reider745/hooks/LevelHooks.java @@ -391,7 +391,7 @@ public static boolean setBlock(Level self, int x, int y, int z, int layer, Block if (direct) { self.sendBlocks(self.getChunkPlayers(cx, cz).values().toArray(Player.EMPTY_ARRAY), new Block[]{block}, UpdateBlockPacket.FLAG_ALL_PRIORITY, block.layer); } else { - ReflectHelper.invokeVoid(self, "addBlockChange", new Object[]{ + ReflectHelper.invoke(self, "addBlockChange", new Object[]{ Level.chunkHash(cx, cz), x, y, z }, long.class, int.class, int.class, int.class); } diff --git a/src/main/java/com/reider745/hooks/RhinoOverrides.java b/src/main/java/com/reider745/hooks/RhinoOverrides.java index 594c3e93f..6d788c526 100644 --- a/src/main/java/com/reider745/hooks/RhinoOverrides.java +++ b/src/main/java/com/reider745/hooks/RhinoOverrides.java @@ -1,9 +1,7 @@ package com.reider745.hooks; import cn.nukkit.utils.MainLogger; -import com.reider745.api.hooks.ArgumentTypes; -import com.reider745.api.hooks.HookController; -import com.zhekasmirnov.innercore.api.NativeCallback; +import com.reider745.api.ReflectHelper; import javassist.CannotCompileException; import javassist.CtClass; import javassist.CtMethod; @@ -16,6 +14,11 @@ import com.reider745.api.hooks.TypeHook; import com.reider745.api.hooks.annotation.Hooks; import com.reider745.api.hooks.annotation.Inject; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.ContextFactory; +import org.mozilla.javascript.ScriptRuntime; + +import java.util.ArrayList; @Hooks(className = "org.mozilla.javascript.JavaMembers") public class RhinoOverrides implements HookClass { @@ -50,4 +53,90 @@ public static void warning(MainLogger nukkitLogger, String message) { logger.warn(message); } } + + public static class ClassLoaderPool extends ClassLoader { + private static final ArrayList loaders = new ArrayList<>(); + + public ClassLoaderPool(ClassLoader parent) { + super(parent); + } + + public static void addClassLoader(ClassLoader loader){ + loaders.add(loader); + } + + public static Class forName(String name) throws ClassNotFoundException { + try{ + return Context.getCurrentContext().getApplicationClassLoader().loadClass(name); + }catch (Exception ignore){} + return Class.forName(name); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + for (ClassLoader loader : loaders) { + try { + return loader.loadClass(name); + } catch (ClassNotFoundException ignored) {} + } + return super.findClass(name); + } + } + + public static Class classOrNull(ClassLoader loader, String className) { + try { + return loader.loadClass(className); + } catch (ClassNotFoundException ex) { + } catch (IllegalArgumentException e) { + // Can be thrown if name has characters that a class name + // can not contain + } + return null; + } + + static boolean testIfCanLoadRhinoClasses(ClassLoader loader) { + Class testClass = ScriptRuntime.ContextFactoryClass; + Class x = classOrNull(loader, testClass.getName()); + if (x != testClass) { + // The check covers the case when x == null => + // loader does not know about testClass or the case + // when x != null && x != testClass => + // loader loads a class unrelated to testClass + return false; + } + return true; + } + + @Inject(className = "org.mozilla.javascript.Context") + public static ClassLoader getApplicationClassLoader(Context self) throws ClassNotFoundException { + ClassLoader applicationClassLoader = ReflectHelper.getField(self, "applicationClassLoader"); + if (applicationClassLoader == null) { + ContextFactory f = self.getFactory(); + ClassLoader loader = f.getApplicationClassLoader(); + if (loader == null) { + ClassLoader threadLoader = Thread.currentThread().getContextClassLoader(); + if (threadLoader != null && testIfCanLoadRhinoClasses(threadLoader)) { + // Thread.getContextClassLoader is not cached since + // its caching prevents it from GC which may lead to + // a memory leak and hides updates to + // Thread.getContextClassLoader + + return new ClassLoaderPool(threadLoader); + } + + // Thread.getContextClassLoader can not load Rhino classes, + // try to use the loader of ContextFactory or Context + // subclasses. + Class fClass = f.getClass(); + if (fClass != ScriptRuntime.ContextFactoryClass) { + loader = fClass.getClassLoader(); + } else { + loader = self.getClass().getClassLoader(); + } + } + applicationClassLoader = new ClassLoaderPool(loader); + ReflectHelper.setField(self, "applicationClassLoader", applicationClassLoader); + } + return applicationClassLoader; + } } diff --git a/src/main/java/com/zhekasmirnov/horizon/launcher/env/ClassLoaderPatch.java b/src/main/java/com/zhekasmirnov/horizon/launcher/env/ClassLoaderPatch.java index 8f0a7513d..472fa6393 100644 --- a/src/main/java/com/zhekasmirnov/horizon/launcher/env/ClassLoaderPatch.java +++ b/src/main/java/com/zhekasmirnov/horizon/launcher/env/ClassLoaderPatch.java @@ -88,12 +88,17 @@ public static synchronized void addClasspath(ClassLoader classLoader, File file) } } } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | RuntimeException e) { - ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); + /*ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); if (classLoader != systemClassLoader) { addClasspath(systemClassLoader, file); return; } - throw new RuntimeException("failed to patch classloader with following error", e); + throw new RuntimeException("failed to patch classloader with following error", e);*/ + /*try { + addClasspath(new URLClassLoader(new URL[]{file.toURL()}), file); + } catch (MalformedURLException ex) { + + }*/ } catch (MalformedURLException e) { throw new RuntimeException("failed to patch classloader with following error", e); } diff --git a/src/main/java/com/zhekasmirnov/horizon/modloader/java/JavaLibrary.java b/src/main/java/com/zhekasmirnov/horizon/modloader/java/JavaLibrary.java index 5c9968599..e7f4e7729 100644 --- a/src/main/java/com/zhekasmirnov/horizon/modloader/java/JavaLibrary.java +++ b/src/main/java/com/zhekasmirnov/horizon/modloader/java/JavaLibrary.java @@ -1,9 +1,14 @@ package com.zhekasmirnov.horizon.modloader.java; +import com.reider745.InnerCoreServer; +import com.reider745.hooks.RhinoOverrides; import com.zhekasmirnov.horizon.launcher.env.ClassLoaderPatch; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -39,13 +44,26 @@ public boolean isInitialized() { } public void initialize() { + final List urls = new ArrayList<>(); for (File dexFile : this.dexFiles) { - ClassLoaderPatch.addDexPath(JavaLibrary.class.getClassLoader(), dexFile, true); + try { + final String filePath = dexFile.getAbsolutePath(); + urls.add(new File( + (filePath.endsWith(".dex") ? filePath.substring(0, filePath.length() - 4) : filePath) + ".jar").toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } } + + final URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), InnerCoreServer.class.getClassLoader()); + RhinoOverrides.ClassLoaderPool.addClassLoader(classLoader); + for (File dexFile : this.dexFiles) + ClassLoaderPatch.addDexPath(classLoader, dexFile, true); + HashMap data = new HashMap<>(); for (String name : this.directory.getBootClassNames()) { try { - Class clazz = Class.forName(name); + Class clazz = classLoader.loadClass(name); Method method = clazz.getMethod("boot", HashMap.class); data.put("class_name", name); method.invoke(null, new HashMap<>(data)); diff --git a/src/main/java/com/zhekasmirnov/innercore/mod/executable/Executable.java b/src/main/java/com/zhekasmirnov/innercore/mod/executable/Executable.java index 8c7f92dcd..2b7221d51 100644 --- a/src/main/java/com/zhekasmirnov/innercore/mod/executable/Executable.java +++ b/src/main/java/com/zhekasmirnov/innercore/mod/executable/Executable.java @@ -1,6 +1,7 @@ package com.zhekasmirnov.innercore.mod.executable; import com.reider745.InnerCoreServer; +import com.reider745.hooks.RhinoOverrides; import com.zhekasmirnov.innercore.api.NativeJavaScript; import com.zhekasmirnov.innercore.api.log.ICLog; import com.zhekasmirnov.innercore.api.mod.API; @@ -166,7 +167,7 @@ public Object call(Context context, Scriptable parent, Scriptable current, Objec return result; } try { - result = new NativeJavaClass(parent, Class.forName(name), false); + result = new NativeJavaClass(parent, RhinoOverrides.ClassLoaderPool.forName(name), false); } catch (ClassNotFoundException e) { result = new NativeJavaPackage(name); }