2014-12-04 3 views
1

Я пытаюсь создать плагин-систему, где 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; 
    } 

Большое спасибо заранее!

ответ

1

Не то, чтобы это действительно имело значение (поскольку никто на самом деле не просматривает это), или что я даже понимаю, что происходит, но удаляя соответствующий файл плагина в dexTemp.getAbsolutePath() перед его перезагрузкой, он решает проблему.

PS: Знак Tumbleweed, YAY!

+0

Если apk/zip, который вы извлекаете, называется «myapp.apk», в каталоге кеша будет храниться файл «myapp.dex», где 'DexClassLoader' извлекает его. Удалите этот файл перед созданием нового 'DexClassLoader' для нового apk/zip, и он действительно должен работать. – Dauntless