背景情報
このメッセージは、AndroidがでダミーをセットアップClassLoader
しThread.currentThread().setContextClassLoader()
、何かがそのダミークラスローダーを使用しようとしていることを意味します。何かがたくさんある可能性があり、与えられた情報から正確に何を伝えるのは難しいです。ただし、試すことができるトリックがあります。以下を参照してください。とにかく、プロセスに複数のAPKからのコードが含まれる可能性がある場合、Androidはダミークラスローダーをセットアップします。具体的には、以下を使用したことがある場合、Androidはマニフェストを調べますandroid:sharedUserId
。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
android:sharedUserId="triggers.dummy.loader" >
または非標準で実行している場合android:process
<application android:process="triggers.dummy.loader">
警告を取り除く方法
警告を取り除くためにできることは2つあります。
android:sharedUserId
またはを使用しないでくださいandroid:process
ClassLoader
他のコードを実行する前に、使用するAPKを明示的に設定します
ソリューション2を使用するには、いくつかの重要な洞察が必要です。AnyClass
まず、 APK内のすべてのクラスについてAnyClass.class.getClassLoader()
、同じを返しClassLoader
ます。2番、
AnyClass obj = new AnyClass();
Thread.currentThread().setContextClassLoader(obj.getClass().getClassLoader())
と同じです
Thread.currentThread().setContextClassLoader(AnyClass.class.getClassLoader())
Thread.currentThread().setContextClassLoader(getClass().getClassLoader())
第三に、を呼び出すコードの前に呼び出す必要がありますThread.currentThread().getContextClassLoader()
。Thread.setContextClassLoader(getClass().getClassLoader())
第4に、多くのAPKが関係している場合は、最後のAPKがロードされた後に呼び出す必要があります(そうでない場合、最後のAPKをロードすると、手動で設定したものが上書きされます)。そのため、以下のデバッグトリックを使用して、この場合にコンテキストクラスローダーを使用しているユーザーを特定することをお勧めします。次に、その直前にThread.setContextClassLoader(getClass().getClassLoader())
、目的のAPK、通常は最初にロードされるAPK(または、APKが1つしかない場合は、そのAPK;)からクラスを呼び出します。第5に、コンテキストクラスローダーはスレッドごとです。これは、アプリケーションがマルチスレッドの場合に注意する必要があります。
デバッグトリック
ClassLoader.getResources()を呼び出すコードを知りたい場合は、次のように機能するはずです。
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);
}
});
getResources()
これを十分に早い段階で行うと、ダミークラスローダーを呼び出した人に戻るスタックトレースがlogcatに表示されます。