• Uncategorised
  • 0

What kind of code is removed in GraalVM

In GraalVM Native Image mode, the compiler removes unused code to reduce binary size. This means if a class, method, or field is:
Not directly used anywhere in the code AND
Not explicitly registered for reflection

Then GraalVM completely removes it during compilation.


1️⃣ Example: Code That Gets Removed

Consider this Java class:

class UnusedClass {
    public void sayHello() {
        System.out.println("Hello from UnusedClass!");
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

What Happens in GraalVM Native Image Mode?

  • UnusedClass is never instantiated or referenced in the code.
  • Since no reflection configuration is provided, GraalVM removes the class completely.
  • The resulting native binary doesn’t contain UnusedClass at all.

🚨 If later, some code tries to use reflection to access UnusedClass, it will fail with ClassNotFoundException.


2️⃣ Example: Reflection Without Registration (Fails in Native Image)

public class Main {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("Test");
        Object obj = clazz.getDeclaredConstructor().newInstance();
        clazz.getMethod("hello").invoke(obj);
    }
}

class Test {
    public void hello() {
        System.out.println("Hello from Test!");
    }
}

💡 Why does this fail in Native Image?

  • The Test class is never instantiated or directly referenced.
  • GraalVM sees no explicit usage and removes it during compilation.
  • At runtime, Class.forName("Test") fails because Test no longer exists.

✔️ Solution: Register it for reflection using @ReflectiveAccess or a JSON config.

3️⃣ Example: Explicit Registration (Prevents Removal)

Solution 1: Use GraalVM Annotation

import com.oracle.svm.core.annotate.ReflectiveAccess;

@ReflectiveAccess  // Tells GraalVM to keep this class
class Test {
    public void hello() {
        System.out.println("Hello from Test!");
    }
}

Solution 2: Use Reflection Config File

Manually tell GraalVM to keep Test by creating a reflect-config.json file:

[
  {
    "name": "Test",
    "allDeclaredMethods": true,
    "allDeclaredConstructors": true
  }
]

Then compile the native image with:

native-image --reflect-config=reflect-config.json -jar myapp.jar

💡 Now, GraalVM keeps Test and its methods, allowing reflection to work!

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *