Skip to content

[Native Image] Advanced obfuscation breaks due to advanced obfuscation #12620

@sgammon

Description

@sgammon

Describe the Issue

When building a Truffle Enterprise-enabled application with -H:AdvancedObfuscation=... active, some built-in classes trip up the obfuscator; specifically, classes originating from truffle-enterprise-svm.jar, which ships with Oracle GraalVM 25.0.1 at $GRAALVM_HOME/lib/truffle/builder/truffle-enterprise-svm.jar.

Some classes in this JAR are already obfuscated, which makes sense. As part of the obfuscation process, presumably, they have had their SourceFile attribute mangled to the static value "stripped":

Image

When the obfuscator kicks in, however, there is code which expects SourceFile to be the name of a source file:

Image Image

Note that the obfuscator doesn't care what the SourceFile attribute is set to, and won't validate it, but needs something to be present which looks like a filename.

Using the latest version of GraalVM can resolve many issues.

GraalVM Version

java version "25.0.1" 2025-10-21 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 25.0.1+8.1 (build 25.0.1+8-LTS-jvmci-b01)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 25.0.1+8.1 (build 25.0.1+8-LTS-jvmci-b01, mixed mode, sharing)

Operating System and Version

Linux CALVIN 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 GNU/Linux

Build Command

(1) Add Truffle Enterprise dependencies to your classpath
(2) Build with -H:AdvancedObfuscation=... enabled

Expected Behavior

(1) Make an Oracle GraalVM project that uses Truffle
(2) Turn on -H:AdvancedObfuscation=export-mapping
(3) It works and builds an obfuscated binary + exported mapping

Actual Behavior

(1) Make an Oracle GraalVM project that uses Truffle
(2) Turn on -H:AdvancedObfuscation=export-mapping
(3) Crashes instead of finishing; crash occurs during second-phase of build, after obfuscation data has been collected

Steps to Reproduce

(1) Make an Oracle GraalVM project that uses Truffle
(2) Turn on -H:AdvancedObfuscation=export-mapping
(3) Observe crash

Additional Context

I wrote a small tool called sourcefile-attr-fixer which works around this issue. It can be invoked against a JAR to rewrite SourceFile attributes to have a filename-like string; for classes that aren't obfuscated, it will try to use the class name. For classes that are obfuscated, it will deterministically come up with a name to use.

Applying this tool to truffle-enterprise-svm.jar fixes it in-place:
Image

...and then -H:AdvancedObfuscation=... resumes working again.

Directions to use the tool are listed in the README, and it is posted as a Docker container for easy use.

Build Log Output and Error Messages

The build process encountered an unexpected error:

com.oracle.svm.core.util.VMError$HostedError: InternalFeature defined by com.oracle.svm.enterprise.hosted.obfuscation.i unexpectedly failed with a(n) java.lang.ArrayIndexOutOfBoundsException
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:86)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.handleFeatureError(FeatureHandler.java:304)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:95)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:751)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:534)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:548)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:761)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.start(NativeImageGeneratorRunner.java:163)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:111)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.p$c.c(stripped:446)
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.p$c$a.a(stripped:407)
        at java.base/java.util.stream.Collectors.lambda$toMap$0(Collectors.java:1642)
        at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
        at java.base/java.util.HashMap$EntrySpliterator.forEachRemaining(HashMap.java:1859)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:723)
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.p$c$a.a(stripped:407)
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.p$c.hh(stripped:442)
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.p$c.hg(stripped:418)
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.p.gX(stripped:228)
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.i.gL(stripped:182)
        at com.oracle.svm.svm_enterprise/com.oracle.svm.enterprise.hosted.obfuscation.i.afterImageWrite(stripped:140)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.lambda$doRun$8(NativeImageGenerator.java:751)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:93)
        ... 6 mor

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions