Avoid initializing class when resolving lambda type. #3
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Related to McModLauncher/modlauncher#67
Although Forge does not support OpenJ9, I think typetools, as an upstream library, should support it as much as possible.
This issue is not the same as jhalterman#47 which has been fixed in 8059d5e. Let's analyze what happened on FarmersDelight when using OpenJ9.
Considering a simple example below:
Main.java
:Test.java
:Test class will throw an exception when initializing.
When we run this use case with different JVMs, the console will output:
From the above output, we will find that OpenJ9 initializes the target class when calling
ConstantPool#getMethodAt
and swallows the exception, then it cannot obtain the corresponding method correctly.If we change
cp.getMethodAt(i)
tocp.getMethodAtIfLoaded(i)
, the result will be:We will find
Test
class was not initialized and even not initialized whenTest.test
being invoked (this looks like an openj9 issue (eclipse-openj9/openj9#12016) but I don’t think the problem is very serious ), so we can usecp.getMemberRefInfoAt
and reflection to find target method.However, if we comment out the throw statement in static block, these two JVMs will get the method correctly:
Specific this test case to FarmersDelight:
If we try to initialize
CropPatchGeneration
between these two lines:https://github.com/vectorwing/FarmersDelight/blob/59e9a8e6e6e660c43ab8143aa447f099315d1478/src/main/java/vectorwing/farmersdelight/FarmersDelight.java#L34-L35
then run the mod with Hotspot, an exception will be thrown:
The problem is obvious. When typetools analyzes the lambda under OpenJ9, it accidentally initializes the
CropPatchGeneration
class that should not be initialized, and swallowed the exception. Therefore, typetools cannot find the correct method in this line:typetools/src/main/java/net/jodah/typetools/TypeResolver.java
Line 731 in 8d0815a
This PR replaced
ConstantPool#getMethodAt
toConstantPool#getMethodAtIfLoaded
to avoid initializing class and if the method ha not been loaded, useConstantPool#getMemberRefInfoAt
and reflection to find the method.