4

我想知道是否可以打包(或序列化) aClassLoader以通过 a 将其发送Message到 Android 中的另一个进程。ClassLoader没有实现Parcelable/ Serializable

关于如何做到这一点的任何提示?提前致谢!

4

3 回答 3

3

类加载器

类加载器基本上是一个哈希表,其条目由类名作为键,并指向加载到 VM 中的字节码。在 VM 本身中加载的字节代码当然是 Java 进程的限制,因为 Java 不允许您操作代码。请注意,字节码已由 JIT VM 编译为特定于 CPU 的代码,并将包含内存位置和其他低级结构。

可以在同一个 VM中共享类加载器(通过序列化或其他方式),因为类加载器仍然能够指向原始字节码。但是,为了序列化然后反序列化到另一个 VM,类加载器必须序列化字节码。还有问题。

序列化类加载器

作为一个思想实验,我们将如何序列化代码以便其他进程可以反序列化它?

我们必须将其作为类大小的块来处理,以便序列化实体具有整个类接口。我们必须将字节码中的指针“解开”到符号。我们还必须复制该类的整个字符串和符号表,以便自省继续工作。

我们刚刚定义的是类文件本身(稍有不同的是类成员的初始化与序列化)

让我重复一遍:类文件 类的序列化版本。

DEX 难题

但是,Android 会将类文件预编译到 DEX 中。这是一个包含 JAR 优化版本的单个文件 - 类彼此预先链接,所有字符串符号位于相同的共享字符串/符号池中。所以,在 Android 中,你最小的可共享组件就是 DEX。

在许多情况下,应用程序或设备制造商会创建一个 ODEX 文件。这是一个已编译到特定 CPU 和架构(包括大端或小端系统)的 DEX 文件。

在 Android 中,您可以将 ODEX 文件视为序列化的类加载器。

远程类加载

问题的症结在于一个进程如何加载对原始进程可见的类文件。yorkw建议了一个他/她发现的类加载器,它的功能类似于我的建议。方法是第一个进程实现类查找服务,返回类字节码。但是,由于上面列出的 DEX 问题,这不能直接在 Android 上运行。

解决方案?

因此,您实施的任何解决方案都将基于 (O)DEX。您基本上需要让您的客户端与您的服务器对话并请求一个 (O)DEX 文件,然后将其作为单个实体加载。加载它将返回您的新类加载器

现在,我从来没有这样做过,Android 完全有可能只允许加载一个 DEX 文件,从而破坏这种方法。YMMV

我真的希望这个讨论会有所帮助......


TL;DR You can't serialize a class loader; however you might be able to persuade another process to load a (O)DEX file which would produce the same result.

于 2012-07-27T00:24:39.023 回答
1

不,很遗憾这是不可能的。ClassLoader 的某些子集可能可以使 parcelable,但我真的反对它。

如果您的问题是您试图从Parcel不同的应用程序中读取自定义类,您应该能够通过将该类复制到另一个应用程序来读取它(确保它在两个应用程序中位于同一个包中)。您所要做的就是在第一个应用程序中将其写入这样的包裹中:

parcel.writeParcelable(myCustomParcelable, 0);

而在另一端,在您收到包裹的地方,请这样阅读:

MyCustomParcelable myCustomParcelable = (MyCustomParcelable)parcel.readParcelable(getClassLoader());
于 2012-07-20T19:53:20.160 回答
1

鉴于 ClassLoader 的强大本机组件以及它的作用,我无法想象以任何方式与其他进程共享 ClassLoader,至少不会以任何有意义的方式。

于 2012-07-20T20:05:58.893 回答