JDK-8349888 : AOTMode=create crashes with EpsilonGC
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 24,25
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2025-02-12
  • Updated: 2025-03-07
  • Resolved: 2025-02-25
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 25
25 b12Fixed
Related Reports
Causes :  
Description
Affects only EpsilonGC. Thus a P3.
Work around is to avoid *creating* AOT cache with -XX:+EpsilonGC. You can still *use* the AOT cache with -XX:+EpsilonGC

===========
Reproduces reliably in current mainline.

$ cat HelloStream.java 
import java.util.*;
import java.util.stream.*;

public class HelloStream {
    public static void main(String ... args) {
        var words = List.of("hello", "fuzzy", "world");
        var greeting = words.stream()
            .filter(w -> !w.contains("z"))
            .collect(Collectors.joining(", "));
        System.out.println(greeting);  // hello, world
    }
}

$ javac HelloStream.java

$ rm -f app.aot*; build/linux-x86_64-server-fastdebug/images/jdk/bin/java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf  -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xmx64m -Xms64m HelloStream; build/linux-x86_64-server-fastdebug/images/jdk/bin/java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf  -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xmx64m -Xms64m -XX:AOTCache=app.aot HelloStream
hello, world
[0.271s][warning][cds] Skipping HelloStream: Unsupported location
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007cbb79c28f80, pid=971605, tid=971608
#
# JRE version: OpenJDK Runtime Environment (25.0) (fastdebug build 25-internal-adhoc.shade.jdk)
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 25-internal-adhoc.shade.jdk, interpreted mode, compressed oops, compressed class ptrs, epsilon gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x628f80]  AOTClassLinker::class_category_name(Klass*)+0x50
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/shade/trunks/jdk/core.971605)
#
# An error report file with more information is saved as:
# /home/shade/trunks/jdk/hs_err_pid971605.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Aborted (core dumped)

Comments
Changeset: a6cc37fd Branch: master Author: Ioi Lam <iklam@openjdk.org> Date: 2025-02-25 05:38:39 +0000 URL: https://git.openjdk.org/jdk/commit/a6cc37fdbe77ff3c1bd8e2332f67f48e3850e56b
25-02-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/23741 Date: 2025-02-24 04:26:09 +0000
24-02-2025

A conservative fix is to avoid doing any AOT CP resolution on classes that we know will be excluded: diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index 1b4b6ffb22c..fefa621f55e 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -847,6 +847,14 @@ void ClassListParser::parse_constant_pool_tag() { } } + if (SystemDictionaryShared::should_be_excluded(ik)) { + if (log_is_enabled(Warning, cds, resolve)) { + ResourceMark rm; + log_warning(cds, resolve)("Cannot aot-resolve constants for %s because it is excluded", ik->external_name()); + } + return; + } + if (preresolve_class) { AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list); } ====================================== Note that we already avoid resolving any lambdas call-sites that *refer* to excluded types (tested by test/hotspot/jtreg/runtime/cds/appcds/LambdaWithOldClass.java). The above patch will extend this to lambdas call-sites that are *in* excluded types.
12-02-2025

Evaluation: this crash happens because Epsilon GC doesn't really do garbage collection, and hence cannot remove weak references used by MethodType. Apply MethodType.java.diff.txt and rebuild JDK. Note that only when Epsilon is used, the method type " ()HelloStream$$Lambda/0x80000000e" remains after the GC. ============================= [Epsilon] $ java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xmx64m -Xms64m -XX:AOTCache=app.aot -Xlog:gc | egrep '(Hello)|(gc)' [0.003s][info][gc] Using Epsilon [0.018s][info][gc] Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups Adding: ()HelloStream$$Lambda/0x80000000e [0.130s][info][gc] GC request for "System.gc()" is ignored Remain: ()HelloStream$$Lambda/0x80000000e <<<<<<< HERE [0.137s][warning][cds] Skipping HelloStream: Unsupported location [Real collectors] $ java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:+UnlockExperimentalVMOptions -XX:-UseEpsilonGC -Xmx64m -Xms64m -XX:AOTCache=app.aot -Xlog:gc | egrep '(Hello)|(gc)' [0.003s][info][gc] Using G1 Adding: ()HelloStream$$Lambda/0x80000000e [0.155s][info][gc] GC(0) Pause Full (System.gc()) 1M->1M(64M) 33.126ms [0.163s][warning][cds] Skipping HelloStream: Unsupported location ============================= The MethodType "()HelloStream$$Lambda/0x80000000e" was created when instantiating an instance of HelloStream$$Lambda (which is stored inside the resolved invokedynamic call site). However, this method type itself is not stored in the call site. After the lambda call site has been linked, the method type becomes unreferenced, and will be removed from the MethodType::internTable after GC has finished. Because Epsilon doesn't remove this method type from the internTable, it will be discovered later during CDS heap copying, leading to a reference to an excluded class, HelloStream.
12-02-2025

The root cause -- when EpisonGC is used, HelloStream$$Lambda is archived: ============== $ java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:AOTCache=app.aot -Xlog:cds+resolve=trace::none | grep Hello Resolved class [ 14] HelloStream -> java.util.List Resolved class [ 28] HelloStream -> java.util.stream.Stream Resolved class [ 36] HelloStream -> java.util.stream.Collectors Resolved class [ 45] HelloStream -> java.lang.String Resolved class [ 48] HelloStream -> java.lang.System Resolved class [ 54] HelloStream -> java.io.PrintStream Resolved class [ 65] HelloStream -> HelloStream Resolved class [ 85] HelloStream -> java.lang.invoke.LambdaMetafactory Resolved invokeinterface [ 19] HelloStream -> java.util.List.stream:()Ljava/util/stream/Stream; Resolved invokeinterface [ 27] HelloStream -> java.util.stream.Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream; Resolved invokeinterface [ 41] HelloStream -> java.util.stream.Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object; Resolved invokevirtual [ 53] HelloStream -> java.io.PrintStream.println:(Ljava/lang/String;)V Resolved invokevirtual [ 61] HelloStream -> java.lang.String.contains:(Ljava/lang/CharSequence;)Z Resolved indy [ 23] HelloStream Skipping HelloStream: Unsupported location Hello Archiving CP entries for HelloStream$$Lambda+0x80000000e archived klass CP entry [ 2]: HelloStream$$Lambda+0x80000000e app => HelloStream$$Lambda+0x80000000e app archived klass CP entry [ 6]: HelloStream$$Lambda+0x80000000e app => java/lang/Object boot archived method CP entry [ 8]: HelloStream$$Lambda+0x80000000e java/lang/Object.<init>:()V => java/lang/Object ============== vs when EpisonGC is not used -- HelloStream$$Lambda is not archived: ============== $ java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:+UnlockExperimentalVMOptions -XX:-UseEpsilonGC -XX:AOTCache=app.aot -Xlog:cds+resolve=trace::none | grep Hello Resolved class [ 14] HelloStream -> java.util.List Resolved class [ 28] HelloStream -> java.util.stream.Stream Resolved class [ 36] HelloStream -> java.util.stream.Collectors Resolved class [ 45] HelloStream -> java.lang.String Resolved class [ 48] HelloStream -> java.lang.System Resolved class [ 54] HelloStream -> java.io.PrintStream Resolved class [ 65] HelloStream -> HelloStream Resolved class [ 85] HelloStream -> java.lang.invoke.LambdaMetafactory Resolved invokeinterface [ 19] HelloStream -> java.util.List.stream:()Ljava/util/stream/Stream; Resolved invokeinterface [ 27] HelloStream -> java.util.stream.Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream; Resolved invokeinterface [ 41] HelloStream -> java.util.stream.Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object; Resolved invokevirtual [ 53] HelloStream -> java.io.PrintStream.println:(Ljava/lang/String;)V Resolved invokevirtual [ 61] HelloStream -> java.lang.String.contains:(Ljava/lang/CharSequence;)Z Resolved indy [ 23] HelloStream Skipping HelloStream: Unsupported location ==============
12-02-2025

Bisection says it started with JDK-8348752, but I think the issue was pre-existing, and JDK-8348752 just exposed it with "default" AOT configs.
12-02-2025

Paging [~iklam], as it relates to JDK-8348752.
12-02-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/23581 Date: 2025-02-12 09:58:46 +0000
12-02-2025

I think we are crashing after feeding `nullptr` to `class_category_name`. That `nullptr` is from `ArchiveBuilder::current()->get_buffered_addr` of `HelloStream`, which is skipped, as per warning message right before the crash.
12-02-2025