Android: "Klasse Loader kann für Prozesse, die mehrere Anwendungen Host"

Was bedeutet diese Nachricht in Eclipse's Logcat für Android?

W/ActivityThread: ClassLoader.getResources: The class loader returned by Thread.getContextClassLoader() may fail for processes that host multiple applications. You should explicitly specify a context class loader. For example: Thread.setContextClassLoader(getClass().getClassLoader()); 

Leider gibt es keinen Kontext für diese Warnung gegeben, also weiß ich nicht, was dieses Problem verursacht und wie ich es lösen kann.

  • Wie funktioniert Multi-Threading in Android?
  • Asynchrone Volley-Anrufe in Android SyncAdapter
  • Wie benutzt man ExecutorService mit Android AsyncTask?
  • Java.lang.IllegalMonitorStateException: Objekt nicht durch Thread gesperrt vor warten ()?
  • Kann ein Runnable einen Wert zurückgeben?
  • Posting Toast Nachricht aus einem Thread
  • Nehmen Sie schwere Berechnungen aus dem Android UI Thread
  • Mehrere Songs mit MediaPlayer gleichzeitig spielen: nur einer spielt wirklich
  • 2 Solutions collect form web for “Android: "Klasse Loader kann für Prozesse, die mehrere Anwendungen Host"”

    Hintergrundinformation

    Die Nachricht bedeutet, dass Android einen Dummy ClassLoader mit Thread.currentThread().setContextClassLoader() , und etwas versucht, diesen Dummy Class Loader zu verwenden. Das etwas kann eine Menge Dinge sein, es ist schwer zu sagen, was genau aus den Informationen gegeben ist. Es gibt einen Trick, den du probieren kannst, siehe unten. Wie auch immer, Android richtet die Dummy-Klasse Loader, wenn es ein Risiko, dass der Prozess Code von mehr als einem APK enthalten könnte. Genauer gesagt, Android sieht in Ihrem Manifest, wenn Sie android:sharedUserId :

     <manifest xmlns:android="http://schemas.android.com/apk/res/android" ... android:sharedUserId="triggers.dummy.loader" > 

    Oder wenn Sie in einem Nicht-Standard- android:process laufen

      <application android:process="triggers.dummy.loader"> 

    Wie loswerden die Warnung

    Es gibt zwei Dinge, die du tun kannst, um die Warnung loszuwerden:

    1. Verwenden Sie nicht android:sharedUserId oder android:process
    2. Explizit festlegen, was APK ClassLoader vor dem Ausführen eines anderen Codes verwenden soll

    Um mit Lösung 2 zu gehen, gibt es einige wichtige Erkenntnisse, die du brauchst. Zuerst wird für jede Klasse AnyClass in einer APK AnyClass.class.getClassLoader() denselben ClassLoader . Zweite,

     AnyClass obj = new AnyClass(); Thread.currentThread().setContextClassLoader(obj.getClass().getClassLoader()) 

    ist das gleiche wie

     Thread.currentThread().setContextClassLoader(AnyClass.class.getClassLoader()) 

    Drittens müssen Sie Thread.currentThread().setContextClassLoader(getClass().getClassLoader()) vor dem Code, der Thread.currentThread().getContextClassLoader() . Vielen Dank, wenn viele APKs involviert sind, müssen Sie Thread.setContextClassLoader(getClass().getClassLoader()) nachdem das letzte APK geladen wurde (andernfalls wird das letzte APK überschrieben, was man manuell gesetzt hat). Aus diesem Grund wäre es eine gute Idee, herauszufinden, wer den Kontext-Klassen-Loader in Ihrem Fall mit dem folgenden Debug-Trick verwendet. Dann nennen Thread.setContextClassLoader(getClass().getClassLoader()) für eine Klasse aus der gewünschten APK, in der Regel die APK, die zuerst geladen wird (oder, wenn nur eine APK beteiligt ist, dass APK ;). Fünftens ist der Context-Class-Loader pro Thread , den Sie beachten müssen, wenn Ihre Anwendung Multi-Threaded ist.

    Debug-Trick

    Wenn Sie herausfinden möchten, welchen Code ClassLoader.getResources () aufruft, sollte dies funktionieren:

     Thread.currentThread().setContextClassLoader(new ClassLoader() { @Override public Enumeration<URL> getResources(String resName) throws IOException { Log.i("Debug", "Stack trace of who uses " + "Thread.currentThread().getContextClassLoader()." + "getResources(String resName):", new Exception()); return super.getResources(resName); } }); 

    Wenn du das früh genug machst, solltest du in der Logcat eine Stack-Trace sehen, die auf denjenigen zurückkommt, der getResources() auf den Dummy-Class Loader ruft.

    Ich erhielt diese Warnung ohne Android: sharedUserId oder Android: Prozess in meinem Manifest …

    Fand es nur auf einem Emulator …

    Geräte haben die Warnmeldung nicht angezeigt. Geprüft auf Smartphone KitKat 4.4 API 19 und Tablet 5.0.1 API 21.

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.