安卓:"类加载失败可能承载多个应用程序和QUOT过程; [英] Android: "Class loader may fail for processes that host multiple applications"

查看:528
本文介绍了安卓:"类加载失败可能承载多个应用程序和QUOT过程;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是在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:

  1. 请不要使用安卓sharedUserId 安卓过程
  2. 在精确设置APK 的ClassLoader 来运行的任何其他code之前,用什么
  1. Don't use android:sharedUserId or android:process
  2. 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆