JDK-8218173 : exception during StringConcatFactory clinit breaks string concat with no fallback
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 12,13
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2019-01-31
  • Updated: 2021-12-08
  • Resolved: 2020-05-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 15
15 b24Fixed
Related Reports
Relates :  
Description
If we are unlucky enough to throw an OutOfMemoryError in certain StringConcatFactory static initializers, then string concat is permanently broken, even if the OOM condition was temporary.  There is no fallback to StringBuilder, for example.
Comments
[~redestad] Why you removed TestStressG1Humongous.java from ProblemList-graal.txt in these changes? Now JDK-8218176 is failing again in JDK 15.
03-07-2020

URL: https://hg.openjdk.java.net/jdk/jdk/rev/e196fdd59ff6 User: redestad Date: 2020-05-20 09:45:38 +0000
20-05-2020

Peter has a good point, and I verified that after JDK-8245094 there's no issue forcing initialization of the default strategy. I suggest we fix this for the default strategy, which is now simple enough.
18-05-2020

Hi, If the problem here is that a failure in class static initializer renders the class unusable, then perhaps we could try removing the static initializer. What is required for that is replace every: static final Type FIELD_NAME; static { FIELD_NAME = ... } with: @Stable static FIELD_NAME; static Type fieldName() { if (FIELD_NAME == null) { FIELD_NAME = ... } return FIELD_NAME; } ...and then use fieldName() instead of FIELD_NAME in code. WDYT?
16-05-2020

I haven't been able to make progress with this, setting assignee to 'unassigned'.
23-04-2020

I don't think we can come up with a fallback strategy that does not allocate at all, as we need to at least bind some of the bootstrap arguments (recipe and constants) to a method handle. Also, there isn't a whole lot of allocation going on in MethodHandleInlineCopyStrategy static initializer in the first place. But the problem to fix is not so much the failure upon OOM itself, but the fact that the strategy class is permanently broken after OOM in the static initializer, causing every linking of a string concatenation to fail from there on. I can think of two possible solutions: One is to catch the NoClassDefFoundError in the bootstrap method and switch to a different strategy, which would solve the problem at hand but is not very elegant. The other possible solution I can think of is to make sure the stringconcat strategy class is initialized early on (during JVM initialization) before there is any potential for memory pressure.
19-02-2019

Hannes: Aleksey might be able to assist you with some aspects of this.
01-02-2019

I am not sure what can we do here: BSM linkage would require doing _something_ that can allocate and fail on OOM again. The only way out is the fallback strategy that does not allocate, which has to use something from java.lang.invoke that does not allocate on its own. I think we'd want to discuss this in the context of JEP 348 (Java Compiler Intrinsics) and generally Project Amber. Reassigning to Jim Laskey who's working in that area today.
01-02-2019

Reassign to [~shade] who owns JEP 280.
01-02-2019

Arranging for an OOM to happen at a specific place is not easy, so I made a temporary modification to force the error: java.lang.OutOfMemoryError: here at java.base/java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy.<clinit>(StringConcatFactory.java:1684) at java.base/java.lang.invoke.StringConcatFactory.generate(StringConcatFactory.java:773) at java.base/java.lang.invoke.StringConcatFactory.doStringConcat(StringConcatFactory.java:682) at java.base/java.lang.invoke.StringConcatFactory.makeConcatWithConstants(StringConcatFactory.java:598) at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:99) at java.base/java.lang.invoke.CallSite.makeSite(CallSite.java:307) at java.base/java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:259) at java.base/java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:249) at Hello.main(Hello.java:15) java.lang.NoClassDefFoundError: Could not initialize class java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy at java.base/java.lang.invoke.StringConcatFactory.generate(StringConcatFactory.java:773) at java.base/java.lang.invoke.StringConcatFactory.doStringConcat(StringConcatFactory.java:682) at java.base/java.lang.invoke.StringConcatFactory.makeConcatWithConstants(StringConcatFactory.java:598) at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:99) at java.base/java.lang.invoke.CallSite.makeSite(CallSite.java:307) at java.base/java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:259) at java.base/java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:249) at Hello.main(Hello.java:20) public static void main(String[] args) throws Exception { try { System.err.println("X " + args[0] + " X"); } catch (Throwable e) { e.printStackTrace(); } try { System.err.println("X " + args[0] + " X"); } catch (Throwable e) { e.printStackTrace(); } }
31-01-2019