安卓:"类加载失败可能承载多个应用程序和QUOT过程; [英] Android: "Class loader may fail for processes that host multiple applications"
问题描述
什么是在Eclipse的logcat的这条消息对于Android是什么意思?
What does this message in Eclipse's logcat for Android mean?
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());
不幸的是,没有给出这一警告的背景下,所以我不知道是什么原因导致这个问题,我怎么能解决这个问题。
Unfortunately, there is no context given as to this warning, so I don't know what causes this problem and how I can resolve it.
推荐答案
该消息意味着Android有设置一个虚拟的ClassLoader
与 Thread.currentThread()。setContextClassLoader()
,和一些尝试使用虚拟的类加载器。在的东西的可以是很多东西,很难从给出的信息到底是什么说。有一个窍门可以试试不过,见下文。不管怎样,Android的设置了虚拟的类加载器时,有这一程序可能包含code从多个APK的风险。更具体地讲,Android的看在你的清单,如果你已经使用安卓sharedUserId
:
Background information
The message means that Android has setup a dummy ClassLoader
with Thread.currentThread().setContextClassLoader()
, and something tries to use that dummy class loader. The something can be a lot of things, it's hard to tell exactly what from the information given. There is a trick you can try though, see below. Anyway, Android sets up the dummy class loader when there is a risk that the process might contain code from more than one APK. More specifically, Android looks in your manifest if you have used android:sharedUserId
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
android:sharedUserId="triggers.dummy.loader" >
如果你在一个不规范的执行安卓过程
<application android:process="triggers.dummy.loader">
如何摆脱警告
的有两件事情可以做,以摆脱警告:
How to get rid of the warning
There are two things you can do to get rid of the warning:
- 请不要使用
安卓sharedUserId
或安卓过程
- 在精确设置APK
的ClassLoader
来运行的任何其他code之前,用什么
- Don't use
android:sharedUserId
orandroid:process
- Explicitly set what APK
ClassLoader
to use before running any other code
要一起去解决方案2,有你需要的一些关键见解。首先,在APK任何类 AnyClass
, AnyClass.class.getClassLoader()
将返回相同的的ClassLoader
。其次,
To go with solution 2, there are some key insights you need. First, for any class AnyClass
in an APK, AnyClass.class.getClassLoader()
will return the same ClassLoader
. Second,
AnyClass obj = new AnyClass();
Thread.currentThread().setContextClassLoader(obj.getClass().getClassLoader())
是相同的
Thread.currentThread().setContextClassLoader(AnyClass.class.getClassLoader())
第三,你需要调用 Thread.currentThread()。setContextClassLoader(的getClass()。getClassLoader())
的code调用<$ C $前C> Thread.currentThread()。getContextClassLoader()。
第四,当牵涉到很多的APK,您需要调用 Thread.setContextClassLoader(的getClass()。getClassLoader())
的在的最后一个APK已经加载(否则装载最后一个APK将覆盖你有什么手动设置)。正因为如此,这将是一个不错的主意,找出使用上下文类加载器的情况下,您通过使用下面的调试伎俩是谁。然后,在正确的,你叫 Thread.setContextClassLoader(的getClass()。getClassLoader())
从所需的APK,通常APK是第一次加载的类(或在的情况下,当只涉及一个APK,那APK)。第五,上下文类加载器的每个线程的,你需要记住,如果你的应用程序是多线程的。
Third, you need to call Thread.currentThread().setContextClassLoader(getClass().getClassLoader())
before the code that calls Thread.currentThread().getContextClassLoader()
.
Fourth, When many APKs are involved, you need to call Thread.setContextClassLoader(getClass().getClassLoader())
after the last APK has been loaded (otherwise loading the last APK will overwrite what you have set manually). Because of that, it would be a good idea to find out who is using the context class loader in you case by using the below debug trick. Then, right before that, you call Thread.setContextClassLoader(getClass().getClassLoader())
for a class from the desired APK, typically the APK that is loaded first (or, in the case when only one APK is involved, that APK ;). Fifth, the context class loader is per thread, which you need to keep in mind if your application is multi-threaded.
如果你想找出code调用中ClassLoader.getResources(),这应该工作:
If you want to find out what code that calls ClassLoader.getResources(), this should work:
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);
}
});
如果你这样做足够早,你应该在logcat中看到,回谁调用堆栈跟踪 getResources()
在虚拟的类加载器。
if you do this early enough, you should see in the logcat a stack trace that goes back to whoever calls getResources()
on the dummy class loader.
这篇关于安卓:&QUOT;类加载失败可能承载多个应用程序和QUOT过程;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!