Skip to content

Commit 2699e07

Browse files
committed
[GR-66019] [GR-65487] Symbol encoder fixes and refactor preserve module selector
PullRequest: graal/21253
2 parents 602cb52 + cdf1922 commit 2699e07

File tree

3 files changed

+64
-17
lines changed

3 files changed

+64
-17
lines changed

docs/reference-manual/native-image/BuildOutput.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,14 +277,28 @@ Unassociated types are displayed when certain types (such as classes, interfaces
277277
If these types contain vulnerabilities, SBOM scanning will not detect them.
278278
To fix this, ensure that proper GAV coordinates (Group ID, Artifact ID, and Version) are defined in the project POM's properties or in _MANIFEST.MF_ using standard formats.
279279

280+
Use the [build report](BuildReport.md) to view included components, their dependencies, and any unassociated types.
280281
For more information, see [Software Bill of Materials](../../security/native-image.md).
281282

282-
#### <a name="glossary-obfuscation"></a>Obfuscation
283-
This section indicates whether obfuscation was applied and provides related statistics.
284-
Obfuscation is applied to your application code and third-party dependencies, but not to the JDK or [Substrate VM](https://github.com/oracle/graal/tree/master/substratevm) code.
285-
The following elements are obfuscated: module, package, and class names; method and source file names in stack traces; and field names in heap dumps.
286-
The following elements are not obfuscated: symbols affected by registrations in reachability metadata; modules and packages that contain a class which loads a resource; annotations; lambdas; and proxies.
287-
Use `-H:EnableObfuscation=export-mapping` to export a build artifact containing the mappings from original to obfuscated names.
283+
#### <a name="glossary-obfuscation"></a>Advanced Obfuscation
284+
This section indicates whether advanced obfuscation was applied.
285+
Advanced obfuscation is applied to your application code and third-party dependencies, but not to the JDK or [Substrate VM](https://github.com/oracle/graal/tree/master/substratevm) code.
286+
287+
**Obfuscated elements include:**
288+
* Module, package, and class names
289+
* Method and source file names (as seen in stack traces)
290+
* Field names (as seen in heap dumps)
291+
292+
**Elements that are _not_ obfuscated:**
293+
* Names affected by registrations in reachability metadata
294+
* Names in preserved code (via `-H:Preserve`)
295+
* Module and package names containing a class that loads a resource
296+
* Names of annotations, lambdas, and proxies
297+
298+
To export a mapping from original to obfuscated names, use `-H:AdvancedObfuscation=export-mapping`.
299+
See the [build report](BuildReport.md) for summary statistics, such as the percentage of class and method names that were obfuscated.
300+
301+
> Native Image obfuscates binaries by removing class files, applying aggressive optimizations, and eliminating dead code. The advanced obfuscation feature also obfuscates symbol names.
288302
289303
#### <a name="glossary-backwards-edge-cfi"></a>Backwards-Edge Control-Flow Integrity (CFI)
290304
Control-Flow Integrity (CFI) can be enforced with the experimental `-H:CFI=HW` option.

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,10 @@ public final class NativeImageClassLoaderSupport {
135135
private final IncludeSelectors preserveSelectors = new IncludeSelectors(SubstrateOptions.Preserve);
136136
private final IncludeSelectors dynamicAccessSelectors = new IncludeSelectors(SubstrateOptions.TrackDynamicAccess);
137137
private boolean includeConfigSealed;
138-
private boolean preserveAll;
139138
private ValueWithOrigin<String> preserveAllOrigin;
140139

141140
public void clearPreserveSelectors() {
142141
preserveSelectors.clear();
143-
preserveAll = false;
144142
preserveAllOrigin = null;
145143
}
146144

@@ -149,7 +147,31 @@ public void clearDynamicAccessSelectors() {
149147
}
150148

151149
public boolean isPreserveMode() {
152-
return !preserveSelectors.classpathEntries.isEmpty() || !preserveSelectors.moduleNames.isEmpty() || !preserveSelectors.packages.isEmpty() || preserveAll;
150+
return !preserveSelectors.classpathEntries.isEmpty() || !preserveSelectors.moduleNames.isEmpty() || !preserveSelectors.packages.isEmpty() || preserveAll();
151+
}
152+
153+
/**
154+
* @return true if {@link PreserveOptionsSupport#PRESERVE_ALL preserve all} is enabled.
155+
*/
156+
private boolean preserveAll() {
157+
return preserveAllOrigin().isPresent();
158+
}
159+
160+
/**
161+
* Returns the {@link PreserveOptionsSupport#PRESERVE_ALL preserve all} selector's
162+
* {@link ValueWithOrigin} if it was set.
163+
*/
164+
public Optional<ValueWithOrigin<?>> preserveAllOrigin() {
165+
return Optional.ofNullable(preserveAllOrigin);
166+
}
167+
168+
/**
169+
* Returns the {@link NativeImageClassLoaderSupport#ALL_UNNAMED module} selector's
170+
* {@link ValueWithOrigin} if it was set. If set, all elements from all class-path entries are
171+
* preserved.
172+
*/
173+
public Optional<ValueWithOrigin<?>> preserveClassPathOrigin() {
174+
return Optional.ofNullable(preserveSelectors.preserveClassPathOrigin);
153175
}
154176

155177
public IncludeSelectors getPreserveSelectors() {
@@ -290,7 +312,7 @@ private ModuleFinder getModulePathsFinder() {
290312
public void loadAllClasses(ForkJoinPool executor, ImageClassLoader imageClassLoader) {
291313
VMError.guarantee(!includeConfigSealed, "This method should be executed only once.");
292314

293-
if (preserveAll) {
315+
if (preserveAll()) {
294316
String msg = """
295317
This image build includes all classes from the classpath and the JDK via the %s option. This will lead to noticeably bigger images and increased startup times.
296318
If you notice '--initialize-at-build-time' related errors during the build, this is because unanticipated types ended up in the image heap.\
@@ -1154,8 +1176,6 @@ public Set<String> getClassNamesToPreserve() {
11541176

11551177
public void setPreserveAll(ValueWithOrigin<String> valueWithOrigin) {
11561178
this.preserveAllOrigin = valueWithOrigin;
1157-
preserveAll = true;
1158-
11591179
}
11601180

11611181
public void setTrackAllDynamicAccess(ValueWithOrigin<String> valueWithOrigin) {
@@ -1183,6 +1203,12 @@ public Stream<Class<?>> getClassesToPreserve() {
11831203
public class IncludeSelectors {
11841204
private static final String CLASS_INCLUSION_SEALED_MSG = "Class inclusion configuration is already sealed.";
11851205

1206+
/**
1207+
* This is non-null if {@link NativeImageClassLoaderSupport#ALL_UNNAMED} is used as a module
1208+
* preserve selector. With this enabled, all elements from all class-path entries are
1209+
* preserved.
1210+
*/
1211+
private ValueWithOrigin<?> preserveClassPathOrigin;
11861212
private final Map<String, IncludeOptionsSupport.ExtendedOptionWithOrigin> moduleNames = new LinkedHashMap<>();
11871213
private final Map<IncludeOptionsSupport.PackageOptionValue, IncludeOptionsSupport.ExtendedOptionWithOrigin> packages = new LinkedHashMap<>();
11881214
private final Map<Path, IncludeOptionsSupport.ExtendedOptionWithOrigin> classpathEntries = new LinkedHashMap<>();
@@ -1283,9 +1309,9 @@ private String originatingOptionString(IncludeOptionsSupport.ExtendedOptionWithO
12831309
public void addModule(String moduleName, IncludeOptionsSupport.ExtendedOptionWithOrigin extendedOptionWithOrigin) {
12841310
VMError.guarantee(!includeConfigSealed, CLASS_INCLUSION_SEALED_MSG);
12851311
if (moduleName.equals(ALL_UNNAMED)) {
1286-
IncludeOptionsSupport.ExtendedOptionWithOrigin includeOptionsSupport = extendedOptionWithOrigin == null ? null
1287-
: new IncludeOptionsSupport.ExtendedOptionWithOrigin(extendedOptionWithOrigin.option(),
1288-
extendedOptionWithOrigin.valueWithOrigin());
1312+
preserveClassPathOrigin = extendedOptionWithOrigin.valueWithOrigin();
1313+
IncludeOptionsSupport.ExtendedOptionWithOrigin includeOptionsSupport = new IncludeOptionsSupport.ExtendedOptionWithOrigin(extendedOptionWithOrigin.option(),
1314+
extendedOptionWithOrigin.valueWithOrigin());
12891315
for (Path path : applicationClassPath()) {
12901316
classpathEntries.put(path, includeOptionsSupport);
12911317
}
@@ -1308,6 +1334,7 @@ public void clear() {
13081334
packages.clear();
13091335
moduleNames.clear();
13101336
classpathEntries.clear();
1337+
preserveClassPathOrigin = null;
13111338
}
13121339

13131340
public Set<Path> classpathEntries() {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.util.Map;
3030
import java.util.concurrent.ConcurrentHashMap;
3131

32+
import com.oracle.svm.core.encoder.IdentitySymbolEncoder;
33+
import com.oracle.svm.core.encoder.SymbolEncoder;
3234
import org.graalvm.nativeimage.c.function.CFunctionPointer;
3335

3436
import com.oracle.graal.pointsto.BigBang;
@@ -70,6 +72,7 @@ public class DynamicHubInitializer {
7072
private final SVMHost hostVM;
7173
private final AnalysisMetaAccess metaAccess;
7274
private final ConstantReflectionProvider constantReflection;
75+
private final SymbolEncoder symbolEncoder;
7376

7477
private final Map<InterfacesEncodingKey, DynamicHub[]> interfacesEncodings;
7578

@@ -84,6 +87,7 @@ public DynamicHubInitializer(BigBang bb) {
8487
this.metaAccess = bb.getMetaAccess();
8588
this.hostVM = (SVMHost) bb.getHostVM();
8689
this.constantReflection = bb.getConstantReflectionProvider();
90+
this.symbolEncoder = SymbolEncoder.singleton();
8791

8892
this.interfacesEncodings = new ConcurrentHashMap<>();
8993

@@ -175,7 +179,7 @@ private boolean shouldRescanHub(ImageHeapScanner heapScanner, DynamicHub hub) {
175179
/**
176180
* For reachable classes, register class's package in appropriate class loader.
177181
*/
178-
private static void registerPackage(ImageHeapScanner heapScanner, Class<?> javaClass, DynamicHub hub) {
182+
private void registerPackage(ImageHeapScanner heapScanner, Class<?> javaClass, DynamicHub hub) {
179183
/*
180184
* Due to using {@link NativeImageSystemClassLoader}, a class's ClassLoader during runtime
181185
* may be different from the class used to load it during native-image generation.
@@ -190,7 +194,9 @@ private static void registerPackage(ImageHeapScanner heapScanner, Class<?> javaC
190194
ClassLoader runtimeClassLoader = ClassLoaderFeature.getRuntimeClassLoader(classloader);
191195
VMError.guarantee(runtimeClassLoader != null, "Class loader missing for class %s", hub.getName());
192196
String packageName = hub.getPackageName();
193-
assert packageName.equals(packageValue.getName()) : Assertions.errorMessage("Package name mismatch:", packageName, packageValue.getName());
197+
if (symbolEncoder instanceof IdentitySymbolEncoder) {
198+
assert packageName.equals(packageValue.getName()) : Assertions.errorMessage("Package name mismatch:", packageName, packageValue.getName());
199+
}
194200
HostedClassLoaderPackageManagement.singleton().registerPackage(runtimeClassLoader, packageName, packageValue, heapScanner::rescanObject);
195201
}
196202
}

0 commit comments

Comments
 (0)