Add graalvm-native-images: Boot 4.1 + GraalVM CE for JDK 25, AOT processing,
the tracing agent, and a real reflection-collision trap Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01EQNA6DJ9VgCtW6zhCE8Xud
This commit is contained in:
+17
@@ -0,0 +1,17 @@
|
||||
package com.ankurm.graalvmdemo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* Companion app for the ankurm.com GraalVM native images post. Built three ways from the same
|
||||
* source: a plain {@code java -jar}, a Spring Boot AOT-processed JVM run, and a GraalVM native
|
||||
* image. See docs/02-building-the-image.md for the exact commands behind each measurement.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class GraalvmDemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GraalvmDemoApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ankurm.graalvmdemo;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* The baseline endpoint used for every startup-time and memory measurement in this chapter --
|
||||
* deliberately trivial, so the numbers reflect the framework and the runtime, not application
|
||||
* work. See docs/01-building-the-image.md.
|
||||
*/
|
||||
@RestController
|
||||
public class HelloController {
|
||||
|
||||
@GetMapping("/hello")
|
||||
public String hello() {
|
||||
return "Hello from a GraalVM native image!";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ankurm.graalvmdemo.report;
|
||||
|
||||
public class JsonReport implements ReportFormat {
|
||||
@Override
|
||||
public String render(String message) {
|
||||
return "{\"report\":\"" + message + "\"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ankurm.graalvmdemo.report;
|
||||
|
||||
public class PlainTextReport implements ReportFormat {
|
||||
@Override
|
||||
public String render(String message) {
|
||||
return "REPORT: " + message;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.ankurm.graalvmdemo.report;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Loads a {@link ReportFormat} implementation by a class name built at request time from the
|
||||
* {@code format} query parameter -- a stand-in for the real-world "pluggable strategy resolved by
|
||||
* a string from configuration" pattern (a plugin name, a feature flag, a database column).
|
||||
* Nothing here gives GraalVM's build-time static analysis a way to know which classes this
|
||||
* reflective call can reach; see docs/02-the-reflection-trap.md for the real failure and its fix.
|
||||
*/
|
||||
@RestController
|
||||
public class ReportController {
|
||||
|
||||
@GetMapping("/report")
|
||||
public String report(@RequestParam(defaultValue = "plain") String format, @RequestParam(defaultValue = "quarterly numbers") String message) {
|
||||
String simpleName = "plain".equals(format) ? "PlainTextReport" : "JsonReport";
|
||||
String className = "com.ankurm.graalvmdemo.report." + simpleName;
|
||||
try {
|
||||
Class<?> clazz = Class.forName(className);
|
||||
ReportFormat instance = (ReportFormat) clazz.getDeclaredConstructor().newInstance();
|
||||
return "OK via reflection on " + className + ": " + instance.render(message);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
return "REFLECTION-FAILED class=" + className + " exception=" + e.getClass().getName() + " message=" + e.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ankurm.graalvmdemo.report;
|
||||
|
||||
/**
|
||||
* Deliberately loaded by class name at runtime, never referenced by a Spring bean definition or a
|
||||
* static {@code new PlainTextReport()} anywhere in this codebase -- see docs/02-the-reflection-trap.md
|
||||
* for why that specific shape is what breaks under GraalVM's closed-world analysis.
|
||||
*/
|
||||
public interface ReportFormat {
|
||||
String render(String message);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"reflection": [
|
||||
{
|
||||
"type": "com.ankurm.graalvmdemo.report.PlainTextReport",
|
||||
"methods": [
|
||||
{ "name": "<init>", "parameterTypes": [] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "com.ankurm.graalvmdemo.report.JsonReport",
|
||||
"methods": [
|
||||
{ "name": "<init>", "parameterTypes": [] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
spring:
|
||||
application:
|
||||
name: graalvm-native-images
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health
|
||||
|
||||
logging:
|
||||
pattern:
|
||||
console: "%msg%n"
|
||||
Reference in New Issue
Block a user