RFR: 8276184: Exclude lambda proxy class from the CDS archive if its caller class is excluded [v3]
Ioi Lam
iklam at openjdk.java.net
Fri Nov 5 17:13:17 UTC 2021
On Thu, 4 Nov 2021 22:24:33 GMT, Calvin Cheung <ccheung at openjdk.org> wrote:
>> The proposed patch has been redone completely to address the problem when a caller class is being excluded
>> from the archive, the associated lambda proxy class(es) was not excluded.
>>
>> The caller class could be excluded if:
>> - it is signed;
>> - it has been redefined after its lambda proxy class was created.
>
> Calvin Cheung has updated the pull request incrementally with one additional commit since the last revision:
>
> remove trailing whitespace
Looks good. I have some comments about a potential bug and suggestion for more testing.
Also, SystemDictionaryShared::cleanup_lambda_proxy_class_dictionary() is called separately for static and dynamic dumps. I think we should move this function to the end of
SystemDictionaryShared::check_excluded_classes().
src/hotspot/share/classfile/systemDictionaryShared.cpp line 1617:
> 1615: InstanceKlass* caller_ik = key.caller_ik();
> 1616: if (SystemDictionaryShared::check_for_exclusion_impl(caller_ik, true)) {
> 1617: // If the caller class is excluded, unregister all the associated lambda proxy classes so that
As we discussed offline, I think we should add a comment here that SystemDictionaryShared::is_excluded_class() cannot be called because with dynamic dumps, caller_ik could be a class in the base archive.
Also, I think we should test different combinations of how a proxy class can be excluded by the two conditions in this function:
(1) caller_ik is excluded
(2) proxy itself is excluded (because it implements an interface with an old class version
(3) both (1) and (2) are true
src/hotspot/share/classfile/systemDictionaryShared.cpp line 1626:
> 1624: for (int i = 0; i < info._proxy_klasses->length(); i++) {
> 1625: InstanceKlass* ik = info._proxy_klasses->at(i);
> 1626: if (SystemDictionaryShared::check_for_exclusion_impl(ik, true)) {
With the original code, if the list has two elements, only the first one is removed -- after the first iteration, `i` becomes 1, but `_proxy_klasses->length()` is also 1, and thus the loop will terminate.
I think the loop should be reversed:
for (int i = info._proxy_klasses->length() - 1; i >= 0; i--) {
if (...) {
info._proxy_klasses->remove_at(i);
}
}
For test coverage, we should also have two test case:
- caller class Foo1 that uses a single instance of an lambda based on old interface
- caller class Foo2 that uses two instances of an lambda based on old interface
src/hotspot/share/classfile/systemDictionaryShared.hpp line 190:
> 188:
> 189: public:
> 190: static bool check_for_exclusion_impl(InstanceKlass* k, bool silent);
Since check_for_exclusion_impl is used only by CleanupDumpTimeLambdaProxyClassTable, I think it's better to keep it private, but declare CleanupDumpTimeLambdaProxyClassTable as a friend class of SystemDictionaryShared. We already do that for ExcludeDumpTimeSharedClasses.
test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RedefineCallerClassTest.java line 29:
> 27: * @summary If the caller class is redefined during dump time, the caller class
> 28: * and its lambda proxy class should not be archived.
> 29: * @requires vm.cds
Add `@bug .....`
test/hotspot/jtreg/runtime/cds/appcds/test-classes/Hello.java line 28:
> 26: public static void main(String args[]) {
> 27: System.out.println("Hello World");
> 28: System.out.println(getRunnable());
Since this class is used by many test cases, I think it's better to control its behavior by
if (args.length > 1 && args[0].equals("testlambda")) {
System.out.println(getRunnable());
}
And also add `@bug JDK-8276184` and a note in SignJar.java, something like "testlambda is for testing JDK-8276184".
-------------
PR: https://git.openjdk.java.net/jdk/pull/6205
More information about the hotspot-runtime-dev
mailing list