Я пытаюсь создать плагин-систему, где DexClassLoader извлекает код из других установленных apks, содержащих фрагменты (мои плагины), и показывая их на моем хосте. Это работает неплохо.DexClassLoader, reload Код не работает с Signal 7
Я также хочу, чтобы плагины были горячими, это означает, что я могу изменить код из плагина, установить его новым, и узел заметит и загрузит новый код. Это также работает, если я меняю код в первый раз. (Хотя я думал, что это не должно, кажется, у меня есть неправильное понимание этого кода:
try {
requiredClass = Class.forName(fullName);
} catch(ClassNotFoundException e) {
isLoaded = false;
}
)
Если я пытаюсь это во второй раз с тем же плагином, хозяин выключается при requiredClass = classLoader.loadClass(fullName);
с чем-то вроде
LibC фатальный сигнал 7 (SIGBUS) в 0x596ed4d6 (код = 2), резьба 28814 (ctivityapp.host)
Кто-нибудь имеет более глубокое понимание функциональности DexClassLoader и может сказать мне, что здесь происходит? Я совсем застрял в этом.
Heres полный код метода загрузки чужой код:
/**
* takes the name of a package as String, and tries to load the code from the corresponding akp using DexclassLaoder.
* Checking if a package is a valid plugin must be done before calling this.
* The Plugin must contain a public class UI that extends Fragment and implements plugin as a starting point for loading
* @param packageName The full name of the package, as String
* @return the plugins object if loaded, null otherwise
*/
private Plugin attachPluginToHost(String packageName) {
try {
Class<?> requiredClass = null;
final ApplicationInfo info = context.getPackageManager().getApplicationInfo(packageName,0);
final String apkPath = info.sourceDir;
final File dexTemp = context.getDir("temp_folder", 0);
final String fullName = packageName + ".UI";
boolean isLoaded = true;
// Check if class loaded
try {
requiredClass = Class.forName(fullName);
} catch(ClassNotFoundException e) {
isLoaded = false;
}
if (!isLoaded) {
final DexClassLoader classLoader = new DexClassLoader(apkPath, dexTemp.getAbsolutePath(), null, context.getApplicationContext().getClassLoader());
requiredClass = classLoader.loadClass(fullName);
}
if (null != requiredClass) {
// Try to cast to required interface to ensure that it's can be cast
final Plugin plugin = Plugin.class.cast(requiredClass.newInstance());
installedPlugins.put(plugin.getName(), plugin);
return plugin;
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
Большое спасибо заранее!
Если apk/zip, который вы извлекаете, называется «myapp.apk», в каталоге кеша будет храниться файл «myapp.dex», где 'DexClassLoader' извлекает его. Удалите этот файл перед созданием нового 'DexClassLoader' для нового apk/zip, и он действительно должен работать. – Dauntless