Skip to content
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

Method reference lambdas are not supported on IBM JDK #47

Open
giamma opened this issue Jan 11, 2019 · 4 comments
Open

Method reference lambdas are not supported on IBM JDK #47

giamma opened this issue Jan 11, 2019 · 4 comments

Comments

@giamma
Copy link

giamma commented Jan 11, 2019

The IBM J9 JDK 8 does not have the private native method Class.getConstantPool().
Please note the J9 is the product name while the JDK level is Java 8.

When the static initialization is performed this results in a run-time error which is ignored in the catch block and the code probably assumes that this is the case because the JDK is < 8 and turns off boolean RESOLVES_LAMBDAS used to indicate whether lambdas are supported or not.

When later a lambda is to be processed a null is returned.

The only possible work around is to not use method references any more.

While version 8 of IBM JDK is only available via commercial subscription, later releases can be downloaded for free from the Adopt OpenJDK site under the name "Open J9".

@giamma giamma changed the title Method reference lambdas are not supported on IBM JDK - leads to NPE Method reference lambdas are not supported on IBM JDK Jan 11, 2019
@jhalterman
Copy link
Owner

Would be happy to take a PR for this.

@giamma
Copy link
Author

giamma commented Jan 14, 2019

Hi,

I did a bit of research, looking into the Oracle JDK and IBM JDK source code.

In IBM JDK >= 9 access to constant pool takes place in the exact same way as the Oracle JDK, meaning that the Class object provides the native method which returns the ConstantPool.

However, In IBM JDK 8 the java.lang package contains a package-visible class named Access, i.e. java.lang.Access which provides a method to get the constant pool given a class object:

final class Access  implements sun.misc.JavaLangAccess {
  // --- CUT ---
  public native sun.reflect.ConstantPool getConstantPool(Class<?> paramClass);
  // --- CUT ---
}

So to access the constant pool for a given class the following code could be used:
new java.lang.Access().getConstantPool( class );
(of course via reflection as Access is not accessible).

But even better, the Access class implements sun.misc.JavaLangAccess, and there is a factory method to instantiate it in class: sun.misc.SharedSecrets.getJavaLancAccess()
If you change your code to obtain the constant pool via JavaLangAccess and you first obtain the JavaLangAccess via sun.misc.SharedSecrets in JDK 8 and via jdk.internal.misc.SharedSecrets in JDK >= 9 then your code should be portable across all versions of both Oracle and IBM JDKs.

@jhalterman
Copy link
Owner

Thanks for digging into this. Care to submit a PR? :)

@giamma
Copy link
Author

giamma commented Jan 15, 2019

I don't have much time now, let's see.

giamma added a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma added a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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.
- Travis file changed to also run tests on IBM OpenJ9 11.
giamma pushed a commit to giamma/typetools that referenced this issue Jan 15, 2019
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.
giamma added a commit to giamma/typetools that referenced this issue Jan 15, 2019
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.
@jhalterman jhalterman reopened this Feb 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants