CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-graalvm-sdk--nativeimage

The GraalVM SDK Native Image API allows to customize the native image generation, i.e., the ahead-of-time compilation of Java code to standalone executables

Pending
Overview
Eval results
Files

build-time.mddocs/

Build-time Configuration

Build-time APIs for customizing native image generation, including feature registration, reflection configuration, JNI access control, and lifecycle management. These APIs control what gets included in the final executable during the compilation phase.

Capabilities

Feature System

Comprehensive lifecycle hooks for customizing native image generation through well-defined phases.

/**
 * Interface for intercepting and customizing native image generation
 */
interface Feature {
    /** Check if this feature should be included in the configuration */
    default boolean isInConfiguration(IsInConfigurationAccess access) {
        return true;
    }
    
    /** Called before analysis phase begins */
    default void beforeAnalysis(BeforeAnalysisAccess access) {}
    
    /** Called during analysis phase for iterative processing */
    default void duringAnalysis(DuringAnalysisAccess access) {}
    
    /** Called after analysis phase completes */
    default void afterAnalysis(AfterAnalysisAccess access) {}
    
    /** Called before compilation phase begins */
    default void beforeCompilation(BeforeCompilationAccess access) {}
    
    /** Called after heap layout is determined */
    default void afterHeapLayout(AfterHeapLayoutAccess access) {}
    
    /** Called before image writing */
    default void beforeImageWrite(BeforeImageWriteAccess access) {}
    
    /** Called after image generation completes */
    default void afterImageWrite(AfterImageWriteAccess access) {}
    
    /** Called when feature causes analysis iteration */
    default void onAnalysisExit(OnAnalysisExitAccess access) {}
}

/**
 * Access interface for configuration checking
 */
interface IsInConfigurationAccess {
    /** Find optional class by name */
    Class<?> findClassByName(String className);
    
    /** Get application class loader */
    ClassLoader getApplicationClassLoader();
}

/**
 * Access interface for before analysis phase
 */
interface BeforeAnalysisAccess {
    /** Register class as reachable */
    void registerAsReachable(Class<?> clazz);
    
    /** Register field as accessed */
    void registerAsAccessed(Field field);
    
    /** Register method as reachable */
    void registerAsReachable(Method method);
    
    /** Register constructor as reachable */
    void registerAsReachable(Constructor<?> constructor);
    
    /** Register for reflection */
    void registerForReflectiveInstantiation(Class<?> clazz);
}

/**
 * Access interface for during analysis phase
 */
interface DuringAnalysisAccess extends BeforeAnalysisAccess {
    /** Check if analysis needs to be repeated */
    boolean requireAnalysisIteration();
    
    /** Get reachable classes */
    Set<Class<?>> getReachableClasses();
    
    /** Get reachable methods */
    Set<Method> getReachableMethods();
}

Usage Examples:

// Custom feature implementation
public class MyCustomFeature implements Feature {
    @Override
    public void beforeAnalysis(BeforeAnalysisAccess access) {
        // Register classes for analysis
        access.registerAsReachable(MyImportantClass.class);
        access.registerForReflectiveInstantiation(MyReflectedClass.class);
    }
    
    @Override
    public void duringAnalysis(DuringAnalysisAccess access) {
        // Iterative processing during analysis
        Set<Class<?>> reachable = access.getReachableClasses();
        for (Class<?> clazz : reachable) {
            if (needsSpecialHandling(clazz)) {
                registerSpecialMethods(clazz, access);
                access.requireAnalysisIteration();
            }
        }
    }
    
    @Override
    public void afterAnalysis(AfterAnalysisAccess access) {
        // Final processing after analysis
        System.out.println("Analysis complete, proceeding to compilation");
    }
}

// Register the feature
// (typically done via META-INF/services/org.graalvm.nativeimage.hosted.Feature)

Runtime Reflection Configuration

Register classes, methods, and fields for runtime reflection access.

/**
 * Configuration API for runtime reflection access
 */
class RuntimeReflection {
    /** Register classes for runtime reflection */
    static void register(Class<?>... classes);
    
    /** Register constructors for runtime reflection */
    static void register(Constructor<?>... constructors);
    
    /** Register methods for runtime reflection */
    static void register(Method... methods);
    
    /** Register fields for runtime reflection */
    static void register(Field... fields);
    
    /** Register all declared constructors of classes */
    static void registerAllDeclaredConstructors(Class<?>... classes);
    
    /** Register all declared methods of classes */
    static void registerAllDeclaredMethods(Class<?>... classes);
    
    /** Register all declared fields of classes */
    static void registerAllDeclaredFields(Class<?>... classes);
    
    /** Register classes for reflective instantiation */
    static void registerForReflectiveInstantiation(Class<?>... classes);
}

Usage Examples:

// Register specific elements
RuntimeReflection.register(MyClass.class);
RuntimeReflection.register(MyClass.class.getDeclaredMethod("myMethod"));
RuntimeReflection.register(MyClass.class.getDeclaredField("myField"));

// Register all elements of a class
RuntimeReflection.registerAllDeclaredMethods(MyClass.class);
RuntimeReflection.registerAllDeclaredFields(MyClass.class);

// Register for instantiation
RuntimeReflection.registerForReflectiveInstantiation(MyClass.class);

// In a Feature
public class ReflectionFeature implements Feature {
    @Override
    public void beforeAnalysis(BeforeAnalysisAccess access) {
        // Bulk registration
        RuntimeReflection.register(
            String.class,
            List.class,
            Map.class
        );
        
        // Dynamic registration based on classpath scanning
        registerJsonClasses();
    }
    
    private void registerJsonClasses() {
        // Find and register classes with JSON annotations
        for (Class<?> clazz : findClassesWithAnnotation(JsonSerializable.class)) {
            RuntimeReflection.registerAllDeclaredFields(clazz);
            RuntimeReflection.registerAllDeclaredConstructors(clazz);
        }
    }
}

JNI Access Configuration

Configure JNI access for runtime native method calls.

/**
 * Configuration API for runtime JNI access
 */
class RuntimeJNIAccess {
    /** Register classes for JNI access */
    static void register(Class<?>... classes);
    
    /** Register constructors for JNI access */
    static void register(Constructor<?>... constructors);
    
    /** Register methods for JNI access */
    static void register(Method... methods);
    
    /** Register fields for JNI access */
    static void register(Field... fields);
    
    /** Register all declared constructors for JNI */
    static void registerAllDeclaredConstructors(Class<?>... classes);
    
    /** Register all declared methods for JNI */
    static void registerAllDeclaredMethods(Class<?>... classes);
    
    /** Register all declared fields for JNI */
    static void registerAllDeclaredFields(Class<?>... classes);
}

Usage Examples:

// Register JNI-accessible elements
RuntimeJNIAccess.register(NativeInterface.class);
RuntimeJNIAccess.register(
    NativeInterface.class.getDeclaredMethod("nativeCallback", int.class)
);

// Register all JNI methods
RuntimeJNIAccess.registerAllDeclaredMethods(JNIHelper.class);

// In a Feature for JNI libraries
public class JNIFeature implements Feature {
    @Override
    public void beforeAnalysis(BeforeAnalysisAccess access) {
        // Register classes used by native libraries
        RuntimeJNIAccess.register(
            CallbackHandler.class,
            DataProcessor.class,
            ErrorReporter.class
        );
        
        // Register specific methods called from native code
        try {
            Method callback = CallbackHandler.class.getDeclaredMethod("onEvent", String.class);
            RuntimeJNIAccess.register(callback);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

Class Initialization Configuration

Control when classes are initialized during build time vs runtime.

/**
 * Configuration API for controlling class initialization timing
 */
class RuntimeClassInitialization {
    /** Initialize classes at build time */
    static void initializeAtBuildTime(Class<?>... classes);
    
    /** Initialize classes at build time by name */
    static void initializeAtBuildTime(String... classNames);
    
    /** Initialize classes at runtime */
    static void initializeAtRunTime(Class<?>... classes);
    
    /** Initialize classes at runtime by name */
    static void initializeAtRunTime(String... classNames);
    
    /** Initialize packages at build time */
    static void initializeAtBuildTimePackage(String... packageNames);
    
    /** Initialize packages at runtime */
    static void initializeAtRunTimePackage(String... packageNames);
}

Usage Examples:

// Build-time initialization for constants and utilities
RuntimeClassInitialization.initializeAtBuildTime(
    Constants.class,
    UtilityClass.class,
    "com.example.config"
);

// Runtime initialization for stateful classes
RuntimeClassInitialization.initializeAtRunTime(
    DatabaseConnection.class,
    ThreadPool.class,
    "com.example.runtime"
);

// Package-level control
RuntimeClassInitialization.initializeAtBuildTimePackage("com.example.constants");
RuntimeClassInitialization.initializeAtRunTimePackage("com.example.services");

// In a Feature
public class InitializationFeature implements Feature {
    @Override
    public void beforeAnalysis(BeforeAnalysisAccess access) {
        // Configure based on application needs
        configureLogging();
        configureDatabase();
    }
    
    private void configureLogging() {
        // Logging can be initialized at build time
        RuntimeClassInitialization.initializeAtBuildTime(
            "org.slf4j",
            "ch.qos.logback.classic",
            "ch.qos.logback.core"
        );
    }
    
    private void configureDatabase() {
        // Database connections must be runtime
        RuntimeClassInitialization.initializeAtRunTime(
            "javax.sql",
            "com.zaxxer.hikari"
        );
    }
}

Additional Configuration APIs

Other build-time configuration capabilities.

/**
 * Configuration API for dynamic proxy creation
 */
class RuntimeProxyCreation {
    /** Register interfaces for dynamic proxy creation */
    static void register(Class<?>... interfaces);
}

/**
 * Configuration API for serialization support
 */
class RuntimeSerialization {
    /** Register classes for serialization */
    static void register(Class<?>... classes);
    
    /** Register classes for serialization by name */
    static void register(String... classNames);
}

/**
 * Configuration API for resource access
 */
class RuntimeResourceAccess {
    /** Register resources for runtime access */
    static void addResource(String resource);
    
    /** Register resource bundles */
    static void addResourceBundle(String bundleName);
    
    /** Register resource patterns */
    static void addResourcePattern(String pattern);
}

/**
 * Configuration API for system properties
 */
class RuntimeSystemProperties {
    /** Set system property for runtime */
    static void set(String key, String value);
    
    /** Register system property for access */
    static void register(String key);
}

/**
 * Configuration API for foreign function access
 */
class RuntimeForeignAccess {
    /** Register foreign functions for runtime access */
    static void register(String... functions);
}

/**
 * Transform field values during image building
 */
interface FieldValueTransformer {
    /** Transform field value during build */
    Object transform(Field field, Object receiver, Object value);
}

Usage Examples:

// Proxy configuration
RuntimeProxyCreation.register(MyInterface.class, AnotherInterface.class);

// Serialization support
RuntimeSerialization.register(
    MySerializableClass.class,
    "com.example.data.UserData",
    "com.example.data.Configuration"
);

// Resource access
RuntimeResourceAccess.addResource("config.properties");
RuntimeResourceAccess.addResourceBundle("messages");
RuntimeResourceAccess.addResourcePattern("static/.*\\.html");

// System properties
RuntimeSystemProperties.set("app.version", "1.0.0");
RuntimeSystemProperties.register("user.home");

// Foreign function access
RuntimeForeignAccess.register("malloc", "free", "strlen");

// Field transformation
public class ConfigTransformer implements FieldValueTransformer {
    @Override
    public Object transform(Field field, Object receiver, Object value) {
        if (field.getName().equals("databaseUrl")) {
            // Transform database URL at build time
            return processConfigValue((String) value);
        }
        return value;
    }
}

Complete Feature Example

/**
 * Comprehensive feature demonstrating multiple configuration aspects
 */
public class ApplicationFeature implements Feature {
    @Override
    public void beforeAnalysis(BeforeAnalysisAccess access) {
        configureReflection();
        configureJNI();
        configureInitialization();
        configureResources();
        configureSerialization();
    }
    
    private void configureReflection() {
        // Register framework classes
        RuntimeReflection.register(
            MyController.class,
            MyService.class,
            MyRepository.class
        );
        
        // Register annotation-driven components
        for (Class<?> clazz : findAnnotatedClasses(Component.class)) {
            RuntimeReflection.registerAllDeclaredMethods(clazz);
            RuntimeReflection.registerForReflectiveInstantiation(clazz);
        }
    }
    
    private void configureJNI() {
        // Register native method classes
        RuntimeJNIAccess.register(NativeLibrary.class);
        RuntimeJNIAccess.registerAllDeclaredMethods(JNICallback.class);
    }
    
    private void configureInitialization() {
        // Build-time initialization for constants
        RuntimeClassInitialization.initializeAtBuildTime(
            "com.example.constants",
            "com.example.config"
        );
        
        // Runtime initialization for stateful components
        RuntimeClassInitialization.initializeAtRunTime(
            "com.example.database",
            "com.example.network"
        );
    }
    
    private void configureResources() {
        // Application resources
        RuntimeResourceAccess.addResource("application.properties");
        RuntimeResourceAccess.addResourcePattern("templates/.*");
        RuntimeResourceAccess.addResourceBundle("messages");
    }
    
    private void configureSerialization() {
        // DTO classes for JSON serialization
        for (Class<?> dto : findDTOClasses()) {
            RuntimeSerialization.register(dto);
            RuntimeReflection.registerAllDeclaredFields(dto);
        }
    }
    
    @Override
    public void duringAnalysis(DuringAnalysisAccess access) {
        // Dynamic registration based on analysis results
        boolean hasNewReachableClasses = false;
        
        for (Class<?> clazz : access.getReachableClasses()) {
            if (isFrameworkClass(clazz)) {
                registerFrameworkRequirements(clazz, access);
                hasNewReachableClasses = true;
            }
        }
        
        if (hasNewReachableClasses) {
            access.requireAnalysisIteration();
        }
    }
    
    @Override
    public void afterAnalysis(AfterAnalysisAccess access) {
        // Validation and final setup
        validateConfiguration();
        generateBuildReport();
    }
}

This build-time configuration system provides comprehensive control over native image generation, enabling applications to precisely specify what functionality should be available at runtime while optimizing the final executable size and performance.

Install with Tessl CLI

npx tessl i tessl/maven-org-graalvm-sdk--nativeimage

docs

build-time.md

c-interop.md

index.md

runtime-core.md

tile.json