<div dir="ltr">Hello Ioi,<div>Thanks for your answer; I now understand why the gating of JVMTI when AOTClassLinking is enabled.</div><div><br></div><div>After reading your answer, and reading <a href="https://openjdk.org/jeps/483">https://openjdk.org/jeps/483</a> , can I sum up the situation by saying:</div><div><br></div><div>-XX:+AOTClassLinking (>=Java 25)<br></div><div>* enabled by default when you're training using -XX:AOTMode=create</div><div>* ahead-of-time loading and linking enhances startup time even more than CDS (cf your benchmark in JEP 483 with HelloStream and Spring PetClinic)</div><div>* can not be applied with JVMTI (Java debug), customized java.security.manager</div><div><br></div><div>-XX:-AOTClassLinking (>=Java 25)<br></div><div>* reverts back to "plain" CDS cache</div><div><br></div><div>Thanks again!</div><div><br></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">Le mar. 27 janv. 2026, à 02 h 27, <<a href="mailto:ioi.lam@oracle.com">ioi.lam@oracle.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">When JDWP is used, AOT is disabled by this check:<br>
<br>
<a href="https://github.com/openjdk/jdk/blob/cba7d88ca427984ebb27a1634aab10a62c9eede1/src/hotspot/share/cds/filemap.cpp#L1743-L1748" rel="noreferrer" target="_blank">https://github.com/openjdk/jdk/blob/cba7d88ca427984ebb27a1634aab10a62c9eede1/src/hotspot/share/cds/filemap.cpp#L1743-L1748</a><br>
<br>
The reason we have this check is that when -XX:+AOTClassLinking is <br>
enabled (by default in AOT cache creation), some class initializers are <br>
executed in the AOT assembly phase, and are not executed in the <br>
production run.<br>
<br>
As a result, some breakpoints will not work.<br>
<br>
Here's an example. I have rebuilt the JVM to disable the above check:<br>
<br>
<br>
===============================================================================<br>
<br>
Without AOT cache: you can break at java.lang.invoke.Invokers.<clinit><br>
<br>
===============================================================================<br>
$ jdb -launch -classpath HelloWorld.jar -R-XX:AOTMode=off <br>
-R-XX:AOTCache=hw.aot java.lang.invoke.Invokers<br>
Set uncaught java.lang.Throwable<br>
Set deferred uncaught java.lang.Throwable<br>
Initializing jdb ...<br>
><br>
VM Started: No frames on the current call stack<br>
<br>
main[1] stop in java.lang.invoke.Invokers.<clinit><br>
Deferring breakpoint java.lang.invoke.Invokers.<clinit>.<br>
It will be set after the class is loaded.<br>
main[1] cont<br>
> Set deferred breakpoint java.lang.invoke.Invokers.<clinit><br>
<br>
Breakpoint hit: "thread=main", java.lang.invoke.Invokers.<clinit>(), <br>
line=47 bci=0<br>
<br>
main[1] where<br>
[1] java.lang.invoke.Invokers.<clinit> (Invokers.java:47)<br>
[2] java.lang.invoke.MethodHandleNatives.linkCallSiteImpl <br>
(MethodHandleNatives.java:263)<br>
[3] java.lang.invoke.MethodHandleNatives.linkCallSite <br>
(MethodHandleNatives.java:240)<br>
[4] java.util.ResourceBundle$Control.<clinit> (ResourceBundle.java:2,833)<br>
[5] java.util.ResourceBundle.getDefaultControl <br>
(ResourceBundle.java:1,508)<br>
[6] java.util.ResourceBundle.getDefaultControl <br>
(ResourceBundle.java:1,503)<br>
[7] java.util.ResourceBundle.getBundle (ResourceBundle.java:863)<br>
[8] sun.launcher.LauncherHelper$ResourceBundleHolder.<clinit> <br>
(LauncherHelper.java:124)<br>
[9] sun.launcher.LauncherHelper.getLocalizedMessage <br>
(LauncherHelper.java:532)<br>
[10] sun.launcher.LauncherHelper.abort (LauncherHelper.java:720)<br>
[11] sun.launcher.LauncherHelper.validateMainMethod <br>
(LauncherHelper.java:944)<br>
[12] sun.launcher.LauncherHelper.checkAndLoadMain <br>
(LauncherHelper.java:778)<br>
main[1] cont<br>
> Error: Main method not found in class java.lang.invoke.Invokers, <br>
please define the main method as:<br>
public static void main(String[] args)<br>
or a JavaFX application class must extend javafx.application.Application<br>
<br>
The application exited<br>
<br>
===============================================================================<br>
<br>
With AOT cache: you cannot break at java.lang.invoke.Invokers.<clinit><br>
<br>
===============================================================================<br>
<br>
<br>
$ jdb -launch -classpath HelloWorld.jar -R-XX:AOTMode=on <br>
-R-XX:AOTCache=hw.aot java.lang.invoke.Invokers<br>
Set uncaught java.lang.Throwable<br>
Set deferred uncaught java.lang.Throwable<br>
Initializing jdb ...<br>
><br>
VM Started: No frames on the current call stack<br>
<br>
main[1] stop in java.lang.invoke.Invokers.<clinit><br>
Set breakpoint java.lang.invoke.Invokers.<clinit><br>
main[1] cont<br>
> Error: Main method not found in class java.lang.invoke.Invokers, <br>
please define the main method as:<br>
public static void main(String[] args)<br>
or a JavaFX application class must extend javafx.application.Application<br>
<br>
The application exited<br>
<br>
<br>
On 1/26/26 9:39 PM, Anthony Dahanne wrote:<br>
> Hello all!<br>
> I'm trying to run an AOTCaching optimized app in debug mode; <br>
> unfortunately, it does not seem to be supported.<br>
><br>
> Using a JDK 25.0.1, during the training run I have:<br>
><br>
> ```<br>
> [creator] Temporary AOTConfiguration recorded: application.aot.config<br>
> [creator] Launching child process <br>
> /layers/paketo-buildpacks_bellsoft-liberica/jre/bin/java to assemble <br>
> AOT cache application.aot using configuration application.aot.config<br>
> [creator] Picked up JAVA_TOOL_OPTIONS: <br>
> -Djava.class.path=runner.jar:lib/spring-cloud-bindings-2.0.4.jar <br>
> -agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n <br>
> -XX:+AOTClassLinking -Dspring.context.exit=onRefresh <br>
> -XX:AOTCacheOutput=application.aot <br>
> -XX:AOTConfiguration=application.aot.config -XX:AOTMode=create<br>
> [creator] Reading AOTConfiguration application.aot.config and <br>
> writing AOTCache application.aot<br>
> [creator] [0.262s][warning][aot] Skipping <br>
> io/micrometer/core/instrument/config/InvalidConfigurationException: <br>
> Unlinked class not supported by AOTClassLinking<br>
> [creator] [0.262s][warning][aot] Skipping <br>
> org/springframework/web/servlet/view/freemarker/FreeMarkerView: <br>
> Unlinked class not supported by AOTClassLinking<br>
> [creator] [0.262s][warning][aot] Skipping <br>
> org/springframework/boot/logging/log4j2/Log4J2LoggingSystem: Unlinked <br>
> class not supported by AOTClassLinking<br>
> [creator] [0.263s][warning][aot] Skipping <br>
> org/springframework/core/ReactiveAdapterRegistry$ReactorAdapter: <br>
> Unlinked class not supported by AOTClassLinking<br>
> [creator] AOTCache creation is complete: application.aot <br>
> 56819712 bytes<br>
> [creator] Removed temporary AOT configuration file <br>
> application.aot.config<br>
> ```<br>
><br>
> but at runtime, I have:<br>
> ```<br>
> Picked up JAVA_TOOL_OPTIONS: <br>
> -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties <br>
> -XX:+ExitOnOutOfMemoryError <br>
> -agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n <br>
> -XX:MaxDirectMemorySize=10M -Xmx14945375K -XX:MaxMetaspaceSize=78944K <br>
> -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions <br>
> -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics <br>
> -XX:AOTCache=application.aot <br>
> -Dorg.springframework.cloud.bindings.boot.enable=true<br>
> [0.032s][error][aot] AOT cache has aot-linked classes. It cannot be <br>
> used with JDWP agent<br>
> [0.034s][error][aot] An error has occurred while processing the AOT <br>
> cache. Run with -Xlog:aot for details.<br>
> [0.034s][error][aot] Unable to map shared spaces<br>
> Listening for transport dt_socket at address: 8000<br>
> ```<br>
><br>
> If I enable `-Xlog:aot` at runtime, I have:<br>
><br>
> ```<br>
> Picked up JAVA_TOOL_OPTIONS: -Xlog:aot <br>
> -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties <br>
> -XX:+ExitOnOutOfMemoryError <br>
> -agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n <br>
> -XX:MaxDirectMemorySize=10M -Xmx15196043K -XX:MaxMetaspaceSize=78944K <br>
> -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions <br>
> -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics <br>
> -XX:AOTCache=application.aot <br>
> -Dorg.springframework.cloud.bindings.boot.enable=true<br>
> [0.033s][info][aot] trying to map application.aot<br>
> [0.033s][info][aot] Opened AOT cache application.aot.<br>
> [0.033s][info][aot] The AOT cache was created with UseCompressedOops = <br>
> 1, UseCompressedClassPointers = 1, UseCompactObjectHeaders = 0<br>
> [0.033s][info][aot] Core region alignment: 65536<br>
> [0.033s][info][aot] ArchiveRelocationMode: 1<br>
> [0.033s][info][aot] ArchiveRelocationMode == 1: always map archive(s) <br>
> at an alternative address<br>
> [0.033s][info][aot] Try to map archive(s) at an alternative address<br>
> [0.033s][info][aot] Reserved archive_space_rs [0x0000003000000000 - <br>
> 0x0000003004000000] (67108864) bytes (includes protection zone)<br>
> [0.033s][info][aot] Reserved class_space_rs [0x0000003004000000 - <br>
> 0x0000003008000000] (67108864) bytes<br>
> [0.033s][info][aot] Mapped static region #0 at base <br>
> 0x0000003000010000 top 0x0000003001500000 (ReadWrite)<br>
> [0.033s][info][aot] Mapped static region #1 at base <br>
> 0x0000003001500000 top 0x0000003003200000 (ReadOnly)<br>
> [0.033s][info][aot] Mapped static region #2 at base <br>
> 0x0000ffff5c120000 top 0x0000ffff5c1e0000 (Bitmap)<br>
> [0.069s][info][aot] archived module property jdk.module.main: (null)<br>
> [0.069s][info][aot] archived module property jdk.module.addexports: (null)<br>
> [0.069s][info][aot] archived module property jdk.module.addmods: (null)<br>
> [0.069s][info][aot] archived module property <br>
> jdk.module.enable.native.access: (null)<br>
> [0.069s][info][aot] archived module property jdk.module.addopens: (null)<br>
> [0.069s][info][aot] archived module property jdk.module.addreads: (null)<br>
> [0.069s][info][aot] optimized module handling: enabled<br>
> [0.069s][info][aot] full module graph: enabled<br>
> [0.069s][error][aot] AOT cache has aot-linked classes. It cannot be <br>
> used with JDWP agent<br>
> [0.069s][info ][aot] Unmapping region #0 at base 0x0000003000010000 <br>
> (ReadWrite)<br>
> [0.069s][info ][aot] Region #0 (ReadWrite) is in a reserved space, it <br>
> will be freed when the space is released<br>
> [0.069s][info ][aot] Unmapping region #1 at base 0x0000003001500000 <br>
> (ReadOnly)<br>
> [0.069s][info ][aot] Region #1 (ReadOnly) is in a reserved space, it <br>
> will be freed when the space is released<br>
> [0.069s][info ][aot] Unmapping region #2 at base 0x0000ffff5c120000 <br>
> (Bitmap)<br>
> [0.069s][error][aot] An error has occurred while processing the AOT <br>
> cache. Run with -Xlog:aot for details.<br>
> [0.069s][error][aot] Unable to map shared spaces<br>
> Listening for transport dt_socket at address: 8000<br>
> ```<br>
><br>
> I have tried several variations using ` -XX:+AOTClassLinking` during <br>
> the training run, but that did not change a thing.<br>
><br>
> Is it possible to use AOTCaching when debug is enabled?<br>
><br>
> Thank you!<br>
><br>
><br>
</blockquote></div>