GraalVM Standard Development Kit providing APIs for polyglot language embedding, native AOT compilation, memory-efficient collections, low-level memory access, JNI utilities, and native bridge communication.
—
Build-time class modification system for replacing methods, fields, and types during native image compilation. Note: This API is provided for compatibility only and is not part of the supported public API.
Annotations for identifying which classes to modify during native image compilation.
/**
* Identifies the target class for substitutions
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetClass {
/** Target class to substitute */
Class<?> value() default void.class;
/** Target class name as string (for classes not on classpath) */
String className() default "";
/** Provider for computing target class name dynamically */
Class<? extends Function<TargetClass, String>> classNameProvider() default NoClassNameProvider.class;
/** Target class only on specific platforms */
Class<? extends BooleanSupplier>[] onlyWith() default {};
/** Exclude target class on specific platforms */
Class<? extends BooleanSupplier>[] innerClass() default {};
}
/**
* Fine-grained targeting of specific class elements
*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetElement {
/** Target element name */
String name() default "";
/** Target method parameter types */
Class<?>[] parameters() default {};
/** Target element only on specific platforms */
Class<? extends BooleanSupplier>[] onlyWith() default {};
}Usage Examples:
import com.oracle.svm.core.annotate.*;
// Substitute methods in java.lang.System
@TargetClass(System.class)
final class SystemSubstitutions {
// Target specific method with parameters
@TargetElement(name = "getProperty", parameters = {String.class})
@Substitute
public static String getProperty(String key) {
// Custom implementation for native image
return NativeImageProperties.getProperty(key);
}
}
// Target class by name (when class not available at build time)
@TargetClass(className = "com.example.PlatformSpecific")
final class PlatformSpecificSubstitutions {
@Substitute
public static void platformMethod() {
// Native image compatible implementation
throw new UnsupportedOperationException("Not supported in native image");
}
}
// Conditional targeting based on platform
@TargetClass(value = WindowsSpecificClass.class,
onlyWith = WindowsPlatform.class)
final class WindowsSubstitutions {
@Substitute
public static void windowsOnlyMethod() {
// Windows-specific native implementation
}
}Replace method implementations with native image compatible versions.
/**
* Marks methods that replace original implementations
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Substitute {
/** Handle methods with polymorphic signatures */
boolean polymorphicSignature() default false;
/** Override static modifier detection */
boolean isStatic() default false;
}
/**
* Keep original method alongside substitution
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface KeepOriginal {
}
/**
* Add annotations to original method without changing implementation
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotateOriginal {
}Usage Examples:
@TargetClass(java.util.concurrent.ThreadLocalRandom.class)
final class ThreadLocalRandomSubstitutions {
// Replace problematic method with native image compatible version
@Substitute
public static ThreadLocalRandom current() {
// Use global random instead of thread-local in native image
return GlobalRandom.getInstance();
}
// Keep original for specific use cases
@KeepOriginal
@Substitute
public int nextInt() {
// This preserves original method as backup
return original_nextInt();
}
// Add annotation without changing implementation
@AnnotateOriginal
@TruffleBoundary
public native double nextGaussian();
}
// Handle polymorphic signatures (like MethodHandle.invoke)
@TargetClass(java.lang.invoke.MethodHandle.class)
final class MethodHandleSubstitutions {
@Substitute
@MethodHandle.PolymorphicSignature
public native Object invoke(Object... args) throws Throwable;
@Substitute
@MethodHandle.PolymorphicSignature
public native Object invokeExact(Object... args) throws Throwable;
}Control field behavior and manage class elements during compilation.
/**
* Create alias to access original field or method
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Alias {
/** Accessor methods for private fields */
boolean accessors() default false;
}
/**
* Remove elements from target class
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface Delete {
/** Override static modifier detection */
boolean isStatic() default false;
}
/**
* Inject new fields or methods into target class
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
}
/**
* Generate accessor methods for fields
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectAccessors {
/** Accessor class to generate */
Class<?> value();
}Usage Examples:
@TargetClass(java.lang.Thread.class)
final class ThreadSubstitutions {
// Create alias to access private field
@Alias
private String name;
// Create accessor methods for private field
@Alias
@InjectAccessors(ThreadAccessors.class)
private ThreadGroup group;
// Inject new field into target class
@Inject
private static volatile int nativeThreadCounter = 0;
// Remove problematic method
@Delete
public static native void dumpThreads(Thread[] threads);
// Inject new utility method
@Inject
public static int getNativeThreadCount() {
return nativeThreadCounter;
}
// Use alias in substitution
@Substitute
public String getName() {
return name != null ? name : "native-thread-" + nativeThreadCounter++;
}
}
// Accessor class for generated methods
final class ThreadAccessors {
public static ThreadGroup getGroup(Thread thread) {
// Generated by @InjectAccessors
return null; // Implementation provided by annotation processor
}
public static void setGroup(Thread thread, ThreadGroup group) {
// Generated by @InjectAccessors
}
}Transform static field values during image build for optimization and configuration.
/**
* Recompute static field values at build time
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RecomputeFieldValue {
/** Recomputation strategy */
Kind kind();
/** Declaring class for field reference */
Class<?> declClass() default void.class;
/** Field name for reference */
String name() default "";
/** Make field final after recomputation */
boolean isFinal() default true;
/** Transformation kinds */
enum Kind {
/** Reset to default value (0, null, false) */
Reset,
/** Copy value from another field */
FromAlias,
/** Compute value using custom transformer */
Custom,
/** Set to array length */
ArrayLength,
/** Set to current timestamp */
AtBuildTime
}
}Usage Examples:
@TargetClass(java.lang.System.class)
final class SystemFieldSubstitutions {
// Reset security manager to null in native image
@Alias
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
private static SecurityManager security;
// Copy build-time property value
@Alias
@RecomputeFieldValue(
kind = RecomputeFieldValue.Kind.FromAlias,
name = "buildTimeJavaVersion"
)
private static String javaVersion;
@Inject
private static final String buildTimeJavaVersion = System.getProperty("java.version");
// Custom field transformation
@Alias
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom,
declClass = BuildTimeComputer.class,
name = "computeMemorySize")
private static long maxMemory;
// Set to build timestamp
@Inject
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.AtBuildTime)
private static final long buildTimestamp = System.currentTimeMillis();
}
// Custom field value computer
final class BuildTimeComputer {
public static long computeMemorySize() {
// Compute appropriate memory size for native image
return Runtime.getRuntime().maxMemory() / 2;
}
}Automatically register feature classes for native image generation.
/**
* Automatically register feature classes during image build
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutomaticFeature {
}Usage Examples:
import org.graalvm.nativeimage.hosted.Feature;
// Automatically registered feature
@AutomaticFeature
public class DatabaseConnectionFeature implements Feature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
// Register database driver classes for reflection
access.registerClassForReflection(
com.mysql.cj.jdbc.Driver.class,
org.postgresql.Driver.class
);
}
@Override
public void afterRegistration(AfterRegistrationAccess access) {
// Initialize connection pool
DatabaseConnectionPool pool = new DatabaseConnectionPool();
ImageSingletons.add(DatabaseConnectionPool.class, pool);
}
}
// Feature for JSON serialization support
@AutomaticFeature
public class JsonSerializationFeature implements Feature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
// Find all classes with JSON annotations
for (Class<?> clazz : findJsonAnnotatedClasses()) {
access.registerClassForReflection(clazz);
// Register all fields and methods for JSON processing
for (Field field : clazz.getDeclaredFields()) {
access.registerFieldForReflection(field);
}
for (Method method : clazz.getDeclaredMethods()) {
if (isJsonMethod(method)) {
access.registerMethodForReflection(method);
}
}
}
}
private List<Class<?>> findJsonAnnotatedClasses() {
// Implementation to find JSON-annotated classes
return Collections.emptyList();
}
private boolean isJsonMethod(Method method) {
// Check if method is relevant for JSON processing
return method.getName().startsWith("get") ||
method.getName().startsWith("set") ||
method.getName().startsWith("is");
}
}Create platform-specific substitutions that only apply on certain operating systems or architectures.
// Platform detection interfaces
public interface Platform extends BooleanSupplier {
interface HOSTED_ONLY extends Platform {}
interface LINUX extends Platform {}
interface DARWIN extends Platform {}
interface WINDOWS extends Platform {}
interface AMD64 extends Platform {}
interface AARCH64 extends Platform {}
}Usage Examples:
// Windows-specific substitutions
@TargetClass(value = File.class, onlyWith = Platform.WINDOWS.class)
final class WindowsFileSubstitutions {
@Substitute
public boolean setExecutable(boolean executable) {
// Windows-specific implementation
return WindowsFileSystem.setExecutable(this, executable);
}
}
// Linux-specific substitutions
@TargetClass(value = UnixFileSystem.class, onlyWith = Platform.LINUX.class)
final class LinuxFileSystemSubstitutions {
@Substitute
public long getSpace(File f, int t) {
// Linux-specific disk space implementation
return LinuxNativeFS.getSpace(f.getPath(), t);
}
}
// Architecture-specific optimizations
@TargetClass(value = CRC32.class, onlyWith = Platform.AMD64.class)
final class AMD64CRC32Substitutions {
@Substitute
public void update(byte[] b, int off, int len) {
// AMD64-optimized CRC32 implementation
updateAMD64(b, off, len);
}
private native void updateAMD64(byte[] b, int off, int len);
}
// Custom platform conditions
public final class CustomPlatform implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return System.getProperty("custom.platform.enabled", "false").equals("true");
}
}
@TargetClass(value = CustomClass.class, onlyWith = CustomPlatform.class)
final class ConditionalSubstitutions {
@Substitute
public void customMethod() {
// Only included when custom.platform.enabled=true
}
}// Exception types
public class SubstitutionException extends RuntimeException {
public SubstitutionException(String message);
public SubstitutionException(String message, Throwable cause);
}
// Utility interfaces
public interface BooleanSupplier {
boolean getAsBoolean();
}
public interface Function<T, R> {
R apply(T t);
}
// Internal marker class
final class NoClassNameProvider implements Function<TargetClass, String> {
@Override
public String apply(TargetClass targetClass) {
return "";
}
}
// Build-time transformer interface
public interface FieldValueTransformer {
Object transform(Object receiver, Object originalValue);
}Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-sdk--graal-sdk