-
Notifications
You must be signed in to change notification settings - Fork 93
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
Fix #47 #49
base: master
Are you sure you want to change the base?
Fix #47 #49
Conversation
Originally the static initialization was assuming that the ConstantPool would be accessible via Class.getConstantPool(). However such method only exists in the Oracle JDK and is not provided by the IBM OpenJ9 JDK. But, both JDKs define an interface JavaLangAccess which offers method getConstantPool( Class c ) that returns the constant pool for the given class and the JavaLangAccess can be obtained via factory method SharedSecrets.getJavaLangAccess(). Both SharedSecrets and JavaLangAccess have been relocated from sun.* packages to jdk.internal.* packages in Java 9 or later. Now: - the code obtains the pool using the right classes from the right packages and the behavior is therefore portable across all JDKs available at the time of writing - usage of Unsafe has been also removed - Surefire plugin updated to be able to run TestNG tests. - Surefire tests run in same JVM as maven to (forkedCount=0) to ensure that MAVEN_OPTS are propagated to test execution - Travis file changed to also run tests on IBM OpenJ9 11.
This fixes the issue modelmapper/modelmapper#437 |
jobs: | ||
include: | ||
- stage: adoptopenjdk.net - Eclipse OpenJ9 | ||
env: |
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.
Very nice 👍
It seems that this change would now require users (in Java 9+?) to --add-exports? We should mention that clearly in the README and describe when --add-exports is needed, but overall I'm a bit hesitant to add such a restriction. Can you discuss the tradeoff and why this might be a good idea? |
Interesting conversation related to this issue and the reason of the use of Unsafe class is in the #34 |
I don't think there is an alternative with JDK 10+ but I'd be happy to be proven wrong. The original code was using Unsafe to make accessible getConstantPool of java.lang.Class, located in package java.lang, offered by module java.base which is by default accessible to every other module. The new code to be portable and to work in JDK > 9 uses classes located in jdk.internal and this requires --add-exports. I am not aware of any way to avoid that switch for accessing jdk.internal.* classes but as I said I would be happy to be proven wrong. Unsafe itself starting from JDK >= 10 is located in jdk.internal.* therefore unless we find a way to gain access to classes in such package without --add-exports there is little we can do. Considering that JDK 9 has already reached end of life, and that JDK 11 is the first long term support, the proposed pull request works the same as before on JDK 8 and works in the only supportable way on JDK >= 10. What we could do is reinstate the old logic to behave as before when JDK is exactly 9, because in JDK 9 Unsafe is still located in com.sun.misc. However, I did not do that because nobody should be using JDK 9 as of now since it's unsupported by Oracle, cannot be downloaded for the desktop and as far as I know is also not supported by application servers. Also, to do so we would need to use a lot of reflection due to the fact that the package name is different in Java 10+ (sun.misc -> jdk.internal.misc) |
In my workspace I changed the static block as follows to use the Java 9 JPMS API and a bit of reflection (I did not update the pull request):
In short, it is getting the Module object for Unless I made a mistake, in Eclipse I can compile the code with Java 11 and tests are passing if I run them with either a Java8 launch configuration or a Java11 launch configuration. The class itself is produced in JDK8 format. I think this could be the case because all classes are in Looks like a very dirty hack, not sure what could happen on Java Enterprise Application servers or in more complex scenarios. Your thoughts? |
As an additional comment, while the above does not require the
|
@jhalterman any comments? |
Sorry for the delay... I haven't looked closely at why this is, but the current tests do pass in master right now on JDK 11 (I just added a Travis check for this). Why might that be? |
From what I unsterstood the JDK 11 you enabled it's an OpenJDK instead the issue happens on "IBM OpenJ9 JDK" |
Sure, which is why I'm hesitant to remove support for the current approach for Oracle/Open JDK users (most people) if not necessary. |
If I am not mistaken, unsafe has been moved to a different package in jdk 10 and later so I don't understand how tests using lambdas can pass. |
With JDK 11, the first methods of sun.misc.Unsafe are being retired but the class is yet there. The point here is modelmapper will not work for production (if lambas) for some application servers (for now seems IBM). For what I can see on modelmapper issue without a clear message in logs. This prevent the use of modelmapper for business libraries or at least with a double check for JDK compatibility. |
@jhalterman so the approach could be continue to use Usafe to access private field without the needs of |
How about an adaptive approach - attempt to load the class with Unsafe, if it fails then go through |
For what I understood So @giamma in short if JAVA <= 8 than keep the actual approach instead if JAVA >= 9 than use jdk.internal.Usafe and |
I would even keep the Unsafe approach for 10, 11 if it works, which for the Oracle and OpenJDKs I've tested with, it does. |
Interesting reading for JDK 12 https://openjdk.java.net/jeps/334 |
FYI it seems |
Originally the static initialization was assuming that the ConstantPool
would be accessible via Class.getConstantPool(). However such method
only exists in the Oracle JDK and is not provided by the IBM OpenJ9 JDK.
But, both JDKs define an interface JavaLangAccess which offers method
getConstantPool( Class c ) that returns the constant pool for the given
class and the JavaLangAccess can be obtained via factory method
SharedSecrets.getJavaLangAccess().
Both SharedSecrets and JavaLangAccess have been relocated from sun.*
packages to jdk.internal.* packages in Java 9 or later.
Now:
packages and the behavior is therefore portable across all JDKs
available at the time of writing
that MAVEN_OPTS are propagated to test execution