Reputation: 25873
I'm wondering if it's possible to parcel (or serialize) a ClassLoader
to send it through a Message
to another process in Android. ClassLoader
doesn't implement Parcelable
/Serializable
.
Any hints on how to do this? Thanks in advance!
Upvotes: 4
Views: 1593
Reputation: 19661
A class loader is basically a hash table whose entries are keyed by class name and points to byte code loaded in the VM. Byte code loaded in the VM itself is of course off limits to Java processes, as Java does not allow you to manipulate code. Note that the bytecode has been compiled by the JIT VM into CPU-specific code and will contain memory locations and other low-level constructs.
It is possible to share class loaders (via serialization or otherwise) within the same VM, since the class loader will still be able to point to the original byte code. However, in order to serialize then deserialize into another VM, the class loader would have to serialize the byte code. And there is the problem.
As a thought experiment, how would we serialize the code so that the other process could deserialize it?
We would have to handle this as class-sized chunks so the serialized entity has the entire class interface. We would have to 'unresolve' pointers in the bytecode to symbols. We would also have to copy the entire string and symbol table for the class so introspection continues to work.
What we have just defined is the class file itself (a slight difference being the initialisation vs. serialisation of class members)
Let me repeat that: A class file is the serialized version of a class.
However, Android pre-compiles class files into the DEX. This is a single file which contains an optimized version of a JAR - classes are pre-linked with each other and all strings symbols sit in the same shared string/symbol pools. So, in Android, you the smallest sharable component is the DEX.
In many instances app or device makers create an ODEX file. This is a DEX file that has been compiled to a specific CPU and architecture (including big-endian or little-endian systems).
In Android you can think of the ODEX file as the serialized class loader.
The crux of the problem is how one process can load class files visible to the original process. yorkw suggested a class loader s/he found which does something like what I have suggested. The approach is that the first process implements a class-lookup service, returning the class bytecode. However this won't work on Android directly because of the DEX problem listed above.
Any solution that you implement is therefore going to be based on the (O)DEX. You basically need to have your client talk to your server and request a (O)DEX file, then load it as a single entity. Loading it will return your new class loader
Now, I have never done this, and it is entirely possible that Android allows just one DEX file to be loaded scuppering this approach. YMMV
I do hope this discussion helps...
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.
Upvotes: 3
Reputation: 1553
Given the strong native component of ClassLoader, along with What It Does, I cannot imagine that it is any way possible to share ClassLoaders with other processes, at least not in any way that would be meaningful.
Upvotes: 1
Reputation: 3766
No, it's unfortunately not possible. Some subset of ClassLoader might be possible to make parcelable, but I'd really advice against it.
If your problem is that you're trying to read a custom class from a Parcel
in a different application, you should be able to read it by copying the class to the other application (making sure it's in the same package in both applications). All you have to do is to in the first application write it to a parcel like this:
parcel.writeParcelable(myCustomParcelable, 0);
And in the other end, where you receive the parcel, just read it like this:
MyCustomParcelable myCustomParcelable = (MyCustomParcelable)parcel.readParcelable(getClassLoader());
Upvotes: 1