Improving AppCDS for Custom Loaders

David Holmes david.holmes at oracle.com
Thu May 3 09:01:31 UTC 2018


On 3/05/2018 5:16 PM, Volker Simonis wrote:
> On Thu, May 3, 2018 at 8:55 AM, David Holmes <david.holmes at oracle.com> wrote:
>> Just lurking here but ...
>>
>>> But is this really y relevant use case? Why would I like to create ONE
>>> archive for several apps? This would actually increase the footprint
>>> of a single instance which uses this archive. If I have several apps I
>>> would expect that users create a specific archive for each app to get
>>> the best out of CDS.
>>
>>
>> One app instance may get increased footprint but you presumably use CDS
>> because you have multiple apps running (whether the same or not). These apps
>> all share the core JDK classes from the archive so the overall footprint per
>> instance is less.
>>
> 
> If we just want to share the core JDK classes that's easy. For that we
> could mostly use the default class list (or a slightly extended one)
> which is generated at JDK build time (at JAVA_HOME/lib/classlist).

The point is that you are presumably running multiple instances of 
multiple apps, hence you want to share one set of core classes across 
all, and share the app classes across each app instance.

> If we want to use ONE archive for several applications and we can
> accept to have a bigger footprint if running a single (or just a few)
> applications in parallel I suppose the overhead of simply dumping all
> the classes from the classpathes of the various applications compared
> to an accurate solution where we only dump the actually used classes
> of all applications would be not that big.

But those "accurate" solutions duplicate the core classes and that's a 
waste of footprint.

David
-----

>> David
>> -----
>>
>>
>> On 3/05/2018 4:48 PM, Volker Simonis wrote:
>>>
>>> On Thu, May 3, 2018 at 6:52 AM, Ioi Lam <ioi.lam at oracle.com> wrote:
>>>>
>>>>
>>>>
>>>> On 5/2/18 10:00 AM, Volker Simonis wrote:
>>>>>
>>>>>
>>>>> On Tue, May 1, 2018 at 8:32 PM, Ioi Lam <ioi.lam at oracle.com> wrote:
>>>>>>
>>>>>>
>>>>>> PROBLEM:
>>>>>>
>>>>>> As discussed with Volker and Yumin in previous e-mails, AppCDS has some
>>>>>> experimental support for custom class loaders. However, it's not very
>>>>>> easy
>>>>>> to use.
>>>>>>
>>>>>> For example, you can write a classlist like this:
>>>>>>
>>>>>>        java/lang/Object id: 1
>>>>>>        CustomLoadee id: 2 super: 1 source: /tmp/foo.jar
>>>>>>
>>>>>> The CustomLoadee class will be stored in the shared archive with a CRC
>>>>>> code.
>>>>>> During runtime, if a customed loader wants to load a class of the same
>>>>>> name,
>>>>>> and its classfile has the same size and CRC as the archived class, the
>>>>>> archived version will be loaded. This speeds up class loading by
>>>>>> avoiding
>>>>>> parsing the class file, and saves space by sharing the mmap'ed class
>>>>>> metadata across processes.
>>>>>>
>>>>>> You can see an example test at:
>>>>>>
>>>>>>
>>>>>>
>>>>>> http://hg.openjdk.java.net/jdk/hs/file/46dc568d6804/test/hotspot/jtreg/runtime/appcds/customLoader/HelloCustom.java
>>>>>>
>>>>>> However, the current scheme requires you to specify all the super
>>>>>> classes
>>>>>> and interfaces. There's no support provided by the
>>>>>> -XX:DumpLoadedClassList
>>>>>> option. It can be helped somewhat with Volker's tool:
>>>>>> https://github.com/simonis/cl4cds
>>>>>>
>>>>>>
>>>>>> POSSIBLE SOLUTIONS:
>>>>>>
>>>>>> 1. "Dump-as-you-go". As suggested by Yumin, we can provide a jcmd to
>>>>>> ask
>>>>>> a
>>>>>> running JVM process to dump all of its loaded classes, including those
>>>>>> loaded by custom loaders, into an archive. An alternative is to dump
>>>>>> the
>>>>>> archive at JVM exit time (or when you press Ctrl-C, etc.
>>>>>>
>>>>>> 2. Add information about the custom classes for
>>>>>> -XX:DumpLoadedClassList.
>>>>>> The
>>>>>> trouble is some class loaders don't specify a code source that can be
>>>>>> understood by the built-in class loaders. For example, the "Fat Jars"
>>>>>> would
>>>>>> have a code source like
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> jar:file:/jdk/tmp/test-1.0-SNAPSHOT.jar!/BOOT-INF/lib/validation-api-2.0.1.Final.jar!/
>>>>>>
>>>>>> also, many custom loaders would pre-process the classfile data before
>>>>>> defining the class, so we can't simply archive the version of the class
>>>>>> on
>>>>>> disk.
>>>>>>
>>>>>> One possible solution for #2 is to include the class file data in the
>>>>>> -XX:DumpLoadedClassList output:
>>>>>>
>>>>>>
>>>>>>        java/lang/Object id: 1
>>>>>>        CustomLoadee id: 2 super: 1 source: base64
>>>>>>
>>>>>>
>>>>>>
>>>>>> yv66vgAAADQAFwoABAAQCQAFABEHABIHABMHABQBAAJIaQEADElubmVyQ2xhc3NlcwEABjxpbml0
>>>>>>
>>>>>>
>>>>>>
>>>>>> PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAFmAQADKClJAQAKU291cmNlRmlsZQEA
>>>>>>
>>>>>>
>>>>>>
>>>>>> CkhlbGxvLmphdmEMAAgACQwAFQAWAQAFSGVsbG8BABBqYXZhL2xhbmcvT2JqZWN0AQAISGVsbG8k
>>>>>>
>>>>>>
>>>>>>
>>>>>> SGkBAAFYAQABSQAhAAMABAAAAAAAAgABAAgACQABAAoAAAAdAAEAAQAAAAUqtwABsQAAAAEACwAA
>>>>>>
>>>>>>
>>>>>>
>>>>>> AAYAAQAAAC8ACAAMAA0AAQAKAAAAHAABAAAAAAAEsgACrAAAAAEACwAAAAYAAQAAADEAAgAOAAAA
>>>>>>        AgAPAAcAAAAKAAEABQADAAYACA==
>>>>>>
>>>>>>
>>>>>> Of the 2 solutions:
>>>>>>
>>>>>> #1 seems easier to use, but may require more invasive modifications in
>>>>>> the
>>>>>> VM, especially if you want to be able to continue execution after
>>>>>> dumping.
>>>>>>
>>>>> Not sure what #1 really proposes: dumping the complete .jsa archive at
>>>>> runtime or dumping just the loaded classes.
>>>>>
>>>>> If it's just about dumping the loaded class without generating the
>>>>> .jsa archive there's the problem that by default the VM doesn't store
>>>>> the exact bytes of a class after the class was loaded (except when
>>>>> class transformers are registered). So the class files would have to
>>>>> be re-assembled from the internal VM structures (in the same way this
>>>>> is done for class redefinition) and the resulting class-file may be
>>>>> different from the original bytes (i.e. some attributes may be
>>>>> missing).
>>>>
>>>>
>>>> #1 is for creating the JSA file, not just dumping the class files.
>>>>>
>>>>>
>>>>> If #1 is about creating the whole .jsa archive at runtime (or at VM
>>>>> exit) I think that would be the most attractive solution from a
>>>>> usability point of view although I understand that #2 will be easier
>>>>> to implement in the short term. Regarding the argument that #1 will
>>>>> produce a "binary blob" that's true, but that's already true now when
>>>>> we use "Xshare:dump". I think it should be not to hard to implement a
>>>>> tool based an SA which could introspect a .jsa archive.
>>>>
>>>>
>>>> The argument about the binary blob is to compare it against the text file
>>>> produced by -XX:DumpLoadedClassList.
>>>>
>>>> One use case to consider is when you have a JAR file that contains
>>>> several
>>>> apps that each load a unique set of classes. Today, (assuming that custom
>>>> class loaders are not used), you can run each app once with
>>>> -XX:DumpLoadedClassList, and then do an
>>>>
>>>>       cat *.classlist | sort | uniq > combined.classlist
>>>>
>>>> and then create an archive that would work for all these apps.
>>>>
>>>
>>> But is this really y relevant use case? Why would I like to create ONE
>>> archive for several apps? This would actually increase the footprint
>>> of a single instance which uses this archive. If I have several apps I
>>> would expect that users create a specific archive for each app to get
>>> the best out of CDS.
>>>
>>>> With the binary blob, there's no easy way of doing this. It will be very
>>>> difficult to write a tool to decipher each blob and then somehow combine
>>>> them into a single one.
>>>>
>>>
>>> But if users really wants such a "fat" archive, there's a much easier
>>> way: just dump ALL the classes from the .jar file into the archive. A
>>> class list for this could easily be assembled either with an external
>>> tool like cl4cds (or even a simple shell scripts which converts the
>>> output of `unzip -l <jar-file>` into the correct format). Or, even
>>> simpler, by adding a new option to the VM similar to
>>> -XX:DumpLoadedClassList which dumps all the classes it can find on the
>>> class path (and potentially other, configurable locations).
>>>
>>>> Thanks
>>>> - Ioi
>>>>
>>>>
>>>>>> #2 would be easier to implement, but the classlist might be huge.
>>>>>>
>>>>>> Also, #2 would allow post-processing tools to remove unneeded classes,
>>>>>> or
>>>>>> merge two runs into a single list. The output of #1 is essentially a
>>>>>> binary
>>>>>> blob that's impossible for off-line analysis/optimizations.
>>>>>>
>>>>>>
>>>>>> Any comments, or suggestions for alternatives?
>>>>>>
>>>>>> Thanks
>>>>>> - Ioi
>>>>>>
>>>>>>
>>>>
>>


More information about the hotspot-runtime-dev mailing list