-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8327624: Remove VM implementation that bypass verification for core reflection #21571
base: master
Are you sure you want to change the base?
Conversation
👋 Welcome back mchung! A progress list of the required criteria for merging this PR into |
@mlchung This change is no longer ready for integration - check the PR body for details. |
Webrevs
|
It seems we can now remove |
Good catch! Patch updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/reviewers 2 reviewer
The jdk.internal.reflect
changes look good; need other reviewers to review hotspot changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice cleanup! Great to see all this old code go. Just one mistake ...
Thanks
// If the loader is not the boot loader then throw an exception if its | ||
// superclass is in package jdk.internal.reflect and its loader is not a | ||
// special reflection class loader | ||
if (!this_klass->class_loader_data()->is_the_null_class_loader_data()) { | ||
PackageEntry* super_package = super->package(); | ||
if (super_package != nullptr && | ||
super_package->name()->fast_compare(vmSymbols::jdk_internal_reflect()) == 0 && | ||
!java_lang_ClassLoader::is_reflection_class_loader(this_klass->class_loader())) { | ||
ResourceMark rm(THREAD); | ||
Exceptions::fthrow( | ||
THREAD_AND_LOCATION, | ||
vmSymbols::java_lang_IllegalAccessError(), | ||
"class %s loaded by %s cannot access jdk/internal/reflect superclass %s", | ||
this_klass->external_name(), | ||
this_klass->class_loader_data()->loader_name_and_id(), | ||
super->external_name()); | ||
return; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code should not be removed. The spec for this code should now be:
// If the loader is not the boot loader then throw an exception if its
// superclass is in package jdk.internal.reflect
All we need do is remove the check:
&& !java_lang_ClassLoader::is_reflection_class_loader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that's a good find. Maybe we should write a test for this, if as I assume there isn't one already.
Edit: not with this RFE, just in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// If the loader is not the boot loader then throw an exception if its
// superclass is in package jdk.internal.reflect
This should not be needed. jdk.internal.reflect
is a non-exported package in java.base
module. If another module M
defines a class whose superclass is in jdk.internal.reflect
package, java.base
must export jdk.internal.reflect
package to M
for access. Otherwise, it will fail the super access check, as done in the check below this deleted code.
Reflection::VerifyClassAccessResults vca_result =
Reflection::verify_class_access(this_klass, InstanceKlass::cast(super), false);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test/hotspot/jtreg/runtime/AccessCheckSuper.java
is one test that fails the super class access check. @lfoltan may know whether there are more tests besides this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was necessary back when this was the sun.reflect
package and it was not able to be encapsulated (before modules) to prevent untrusted class loaders from leaking the MagicAccessorImpl
class hierarchy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay ... so such subclass was and remains illegal and is now detected slightly later. That suggests to me this special case was in the wrong place and should have been inside Reflection::verify_class_access
.
Anyway thanks for clarifying full removal is in fact what we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a most impressive example of C.D.E. (code deletion engineering).
I remember when this was written, as an accelerator for the JNI methods, long long before we had method handles to do the same thing more flexibly. I think it was Ken Russell that did the work. And of course I remember Mandy's newer work (3 years ago) fitting method handles into reflection (a move I applauded of course).
As it happens I was just reviewing the reflection implementation this week, to understand its interaction with upcoming Leyden changes to bootstrap sequences. Of course I wondered, "when will we ever retire this older implementation?" Happily, that day has come.
Thanks Mandy!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good cleanup.
I searched the tests as I expected to find some tests exercising -Djdk.reflect.useOldSerializableConstructor but nothing found.
Yes, feeling happy! I have been waiting to get rid of this last piece! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that JDK‑4486457 will finally be able to be made public?
// If the loader is not the boot loader then throw an exception if its | ||
// superclass is in package jdk.internal.reflect and its loader is not a | ||
// special reflection class loader | ||
if (!this_klass->class_loader_data()->is_the_null_class_loader_data()) { | ||
PackageEntry* super_package = super->package(); | ||
if (super_package != nullptr && | ||
super_package->name()->fast_compare(vmSymbols::jdk_internal_reflect()) == 0 && | ||
!java_lang_ClassLoader::is_reflection_class_loader(this_klass->class_loader())) { | ||
ResourceMark rm(THREAD); | ||
Exceptions::fthrow( | ||
THREAD_AND_LOCATION, | ||
vmSymbols::java_lang_IllegalAccessError(), | ||
"class %s loaded by %s cannot access jdk/internal/reflect superclass %s", | ||
this_klass->external_name(), | ||
this_klass->class_loader_data()->loader_name_and_id(), | ||
super->external_name()); | ||
return; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was necessary back when this was the sun.reflect
package and it was not able to be encapsulated (before modules) to prevent untrusted class loaders from leaking the MagicAccessorImpl
class hierarchy.
The old core reflection implementation generates dynamic classes that are special cases in the VM to bypass bytecode verification to workaround various issues [1] [2] [3].
The old core reflection implementation was removed in JDK 22. It's time to remove these VM hacks along with the old implementation of
sun.reflect.ReflectionFactory::newConstructorForSerialization
.After this change,
jdk.internal.reflect.DelegatingClassLoader
no longer exists. Hence the special metaspace for reflection is no longer needed. GTests will need to be updated whenMetaspace::ReflectionMetaspaceType
is removed. Such clean up can be done separately (JDK-8342561).[1] JDK-4486457
[2] JDK-4474172
[3] JDK-6790209
Progress
Issues
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/21571/head:pull/21571
$ git checkout pull/21571
Update a local copy of the PR:
$ git checkout pull/21571
$ git pull https://git.openjdk.org/jdk.git pull/21571/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 21571
View PR using the GUI difftool:
$ git pr show -t 21571
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/21571.diff
Webrev
Link to Webrev Comment