Skip to content

Commit d7bd61c

Browse files
committed
Bugfixes
1 parent 1872df9 commit d7bd61c

File tree

17 files changed

+328
-369
lines changed

17 files changed

+328
-369
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ To reduce overhead, please ensure that the classpath only contains entries that
9999
100100
#### <a name="glossary-reflection-registrations"></a>Reflection Registrations
101101
The number of classes, fields, and methods that are registered for reflection.
102-
Large numbers can cause significant reflection overheads, slow down the build process, and increase the size of the native image (see [method metadata](#glossary-method-metadata)).
102+
Large numbers can cause significant reflection overheads, slow down the build process, and increase the size of the native image (see [reflection metadata](#glossary-reflection-metadata)).
103103
104104
#### <a name="glossary-jni-access-registrations"></a>JNI Access Registrations
105105
The number of classes, fields, and methods that are registered for [JNI][doc_jni] access.
@@ -136,16 +136,16 @@ Therefore, reducing the number of [reachable methods](#glossary-reachability) al
136136
The image heap contains reachable objects such as static application data, metadata, and `byte[]` for different purposes.
137137
138138
##### <a name="glossary-general-heap-data"></a>General Heap Data Stored in `byte[]`
139-
The total size of all `byte[]` objects that are neither used for `java.lang.String`, nor [code metadata](#glossary-code-metadata), nor [method metadata](#glossary-method-metadata), nor [graph encodings](#glossary-graph-encodings).
139+
The total size of all `byte[]` objects that are neither used for `java.lang.String`, nor [code metadata](#glossary-code-metadata), nor [reflection metadata](#glossary-reflection-metadata), nor [graph encodings](#glossary-graph-encodings).
140140
Therefore, this can also include `byte[]` objects from application code.
141141
142142
##### <a name="glossary-code-metadata"></a>Code Metadata Stored in `byte[]`
143143
The total size of all `byte[]` objects used for metadata for the [code area](#glossary-code-area).
144144
Therefore, reducing the number of [reachable methods](#glossary-reachability) also reduces the size of this metadata.
145145
146-
##### <a name="glossary-method-metadata"></a>Method Metadata Stored in `byte[]`
147-
The total size of all `byte[]` objects used for method metadata, a type of reflection metadata.
148-
To reduce the amount of method metadata, reduce the number of [classes registered for reflection](#glossary-reflection-classes).
146+
##### <a name="glossary-reflection-metadata"></a>Reflection Metadata Stored in `byte[]`
147+
The total size of all `byte[]` objects used for reflection metadata, including class, field, method and constructor data.
148+
To reduce the amount of reflection metadata, reduce the number of [elements registered for reflection](#glossary-reflection-registrations).
149149
150150
##### <a name="glossary-graph-encodings"></a>Graph Encodings Stored in `byte[]`
151151
The total size of all `byte[]` objects used for graph encodings.

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/CContext.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -47,6 +47,8 @@
4747
import java.util.Collections;
4848
import java.util.List;
4949

50+
import org.graalvm.nativeimage.Platform;
51+
import org.graalvm.nativeimage.Platforms;
5052
import org.graalvm.nativeimage.c.function.CLibrary;
5153

5254
/**
@@ -58,6 +60,7 @@
5860
*/
5961
@Retention(RetentionPolicy.RUNTIME)
6062
@Target({ElementType.TYPE})
63+
@Platforms(Platform.HOSTED_ONLY.class)
6164
public @interface CContext {
6265

6366
/**

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,11 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String ol
720720
}
721721
};
722722

723+
@SuppressWarnings("unused")//
724+
@APIOption(name = "configure-reflection-metadata")//
725+
@Option(help = "Enable runtime instantiation of reflection objects for non-invoked methods.", type = OptionType.Expert, deprecated = true)//
726+
public static final HostedOptionKey<Boolean> ConfigureReflectionMetadata = new HostedOptionKey<>(true);
727+
723728
@Option(help = "Include a list of methods included in the image for runtime inspection.", type = OptionType.Expert)//
724729
public static final HostedOptionKey<Boolean> IncludeMethodData = new HostedOptionKey<>(true);
725730

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.lang.reflect.AnnotatedElement;
3434
import java.lang.reflect.AnnotatedType;
3535
import java.lang.reflect.Constructor;
36+
import java.lang.reflect.Executable;
3637
import java.lang.reflect.Field;
3738
import java.lang.reflect.GenericDeclaration;
3839
import java.lang.reflect.InvocationTargetException;
@@ -341,6 +342,7 @@ public void setModule(Module module) {
341342
@TargetElement(onlyWith = JDK17OrLater.class)//
342343
@UnknownPrimitiveField int recordComponentsEncodingIndex;
343344

345+
@TargetElement(onlyWith = JDK17OrLater.class)//
344346
@UnknownPrimitiveField int permittedSubclassesEncodingIndex;
345347

346348
@Platforms(Platform.HOSTED_ONLY.class)
@@ -1034,6 +1036,9 @@ private static ReflectionFactory getReflectionFactory() {
10341036
@KeepOriginal
10351037
private static native Field searchFields(Field[] fields, String name);
10361038

1039+
/**
1040+
* @see #filterHidingMethods(Method...)
1041+
*/
10371042
@Substitute
10381043
private static Method searchMethods(Method[] allMethods, String name, Class<?>[] parameterTypes) {
10391044
Method[] methods = filterHidingMethods(allMethods);
@@ -1057,6 +1062,9 @@ private static Method searchMethods(Method[] allMethods, String name, Class<?>[]
10571062
@KeepOriginal
10581063
private static native Field[] copyFields(Field[] arg);
10591064

1065+
/**
1066+
* @see #filterHidingMethods(Method...)
1067+
*/
10601068
@Substitute
10611069
private static Method[] copyMethods(Method[] original) {
10621070
Method[] arg = filterHidingMethods(original);
@@ -1235,6 +1243,9 @@ private String getSimpleBinaryName0() {
12351243
/* See open/src/hotspot/share/prims/jvm.cpp#1522. */
12361244
}
12371245

1246+
/**
1247+
* @see #filterHidingMethods(Method...)
1248+
*/
12381249
@Substitute //
12391250
@SuppressWarnings({"unused"})
12401251
List<Method> getDeclaredPublicMethods(String methodName, Class<?>... parameterTypes) {
@@ -1476,6 +1487,14 @@ private Class<?>[] getPermittedSubclasses0() {
14761487
@KeepOriginal
14771488
native AnnotationType getAnnotationType();
14781489

1490+
@KeepOriginal
1491+
static native byte[] getExecutableTypeAnnotationBytes(Executable ex);
1492+
1493+
/*
1494+
* We need to filter out hiding methods at the last moment. This ensures that the JDK internals
1495+
* see them as regular methods and ensure the visibility of methods is correct, but they should
1496+
* not be returned to application code.
1497+
*/
14791498
private static Method[] filterHidingMethods(Method... methods) {
14801499
List<Method> filtered = new ArrayList<>();
14811500
for (Method method : methods) {
@@ -1510,6 +1529,13 @@ private static AnnotationType getAnnotationType(DynamicHub that) {
15101529
private static class CachedConstructorAccessors {
15111530
@SuppressWarnings("unused")
15121531
private static Constructor<?> getCachedConstructor(DynamicHub that) {
1532+
/*
1533+
* The JavaDoc for the Class.newInstance method states that "The class is initialized if
1534+
* it has not already been initialized". However, it doesn't specify if the absence of a
1535+
* nullary constructor will result in an InstantiationException before the class is
1536+
* initialized. We eagerly initialize the class to conform with JCK tests.
1537+
*/
1538+
that.ensureInitialized();
15131539
return that.companion.getCachedConstructor();
15141540
}
15151541

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/SunReflectTypeSubstitutions.java

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,11 @@
2424
*/
2525
package com.oracle.svm.core.hub;
2626

27-
import java.lang.annotation.Annotation;
2827
import java.lang.reflect.AnnotatedType;
2928
import java.lang.reflect.GenericDeclaration;
3029
import java.lang.reflect.MalformedParameterizedTypeException;
3130
import java.lang.reflect.Type;
3231

33-
import org.graalvm.compiler.core.common.SuppressFBWarnings;
34-
import org.graalvm.util.GuardedAnnotationAccess;
35-
36-
import com.oracle.svm.core.SubstrateUtil;
3732
import com.oracle.svm.core.annotate.Alias;
3833
import com.oracle.svm.core.annotate.Inject;
3934
import com.oracle.svm.core.annotate.RecomputeFieldValue;
@@ -46,7 +41,6 @@
4641
import jdk.vm.ci.meta.ResolvedJavaField;
4742
import sun.reflect.generics.reflectiveObjects.TypeVariableImpl;
4843
import sun.reflect.generics.reflectiveObjects.WildcardTypeImpl;
49-
import sun.reflect.generics.tree.FieldTypeSignature;
5044

5145
/**
5246
* The bounds in TypeVariableImpl and WildcardTypeImpl are lazily computed. We capture the value and
@@ -56,18 +50,13 @@
5650
@TargetClass(sun.reflect.generics.reflectiveObjects.TypeVariableImpl.class)
5751
final class Target_sun_reflect_generics_reflectiveObjects_TypeVariableImpl {
5852

59-
@Alias private String name;
60-
6153
/* Cache the bounds value. */
6254

6355
@Alias @RecomputeFieldValue(kind = Kind.Custom, declClass = TypeVariableBoundsComputer.class) //
6456
private Object[] bounds;
6557

6658
@Alias GenericDeclaration genericDeclaration;
6759

68-
@Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = TypeVariableAnnotationsComputer.class) //
69-
Annotation[] annotations;
70-
7160
@Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = TypeVariableAnnotatedBoundsComputer.class) //
7261
AnnotatedType[] annotatedBounds;
7362

@@ -82,31 +71,6 @@ public GenericDeclaration getGenericDeclaration() {
8271
return genericDeclaration;
8372
}
8473

85-
@Substitute
86-
public Annotation[] getAnnotations() {
87-
return annotations;
88-
}
89-
}
90-
91-
final class Util_sun_reflect_generics_reflectiveObjects_TypeVariableImpl {
92-
93-
/** Emulate the Java class hierarchy. */
94-
static Target_sun_reflect_generics_reflectiveObjects_LazyReflectiveObjectGenerator asLazyReflectiveObjectGenerator(
95-
Target_sun_reflect_generics_reflectiveObjects_TypeVariableImpl typeVariableImpl) {
96-
return SubstrateUtil.cast(typeVariableImpl, Target_sun_reflect_generics_reflectiveObjects_LazyReflectiveObjectGenerator.class);
97-
}
98-
99-
/** Emulate virtual dispatch. */
100-
static Type[] reifyBounds(Target_sun_reflect_generics_reflectiveObjects_TypeVariableImpl typeVariableImpl, FieldTypeSignature[] boundASTs) {
101-
return asLazyReflectiveObjectGenerator(typeVariableImpl).reifyBounds(boundASTs);
102-
}
103-
}
104-
105-
@TargetClass(className = "sun.reflect.generics.reflectiveObjects.LazyReflectiveObjectGenerator")
106-
final class Target_sun_reflect_generics_reflectiveObjects_LazyReflectiveObjectGenerator {
107-
108-
@Alias
109-
native Type[] reifyBounds(FieldTypeSignature[] boundASTs);
11074
}
11175

11276
class TypeVariableBoundsComputer implements RecomputeFieldValue.CustomFieldValueComputer {
@@ -133,18 +97,6 @@ public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original,
13397
}
13498
}
13599

136-
class TypeVariableAnnotationsComputer implements CustomFieldValueComputer {
137-
@Override
138-
public RecomputeFieldValue.ValueAvailability valueAvailability() {
139-
return RecomputeFieldValue.ValueAvailability.BeforeAnalysis;
140-
}
141-
142-
@Override
143-
public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
144-
return GuardedAnnotationAccess.getAnnotations((TypeVariableImpl<?>) receiver);
145-
}
146-
}
147-
148100
@TargetClass(sun.reflect.generics.reflectiveObjects.WildcardTypeImpl.class)
149101
final class Target_sun_reflect_generics_reflectiveObjects_WildcardTypeImpl {
150102

@@ -157,26 +109,6 @@ final class Target_sun_reflect_generics_reflectiveObjects_WildcardTypeImpl {
157109
@Alias //
158110
@RecomputeFieldValue(kind = Kind.Custom, declClass = WildcardTypeImplLowerBoundsComputer.class) //
159111
private Object[] lowerBounds;
160-
161-
@Substitute
162-
public Type[] getUpperBounds() {
163-
Object[] value = upperBounds;
164-
if (value instanceof FieldTypeSignature[]) {
165-
value = Util_sun_reflect_generics_reflectiveObjects_WildcardTypeImpl.reifyBounds(this, (FieldTypeSignature[]) value);
166-
upperBounds = value;
167-
}
168-
return (Type[]) value.clone();
169-
}
170-
171-
@Substitute
172-
public Type[] getLowerBounds() {
173-
Object[] value = lowerBounds;
174-
if (value instanceof FieldTypeSignature[]) {
175-
value = Util_sun_reflect_generics_reflectiveObjects_WildcardTypeImpl.reifyBounds(this, (FieldTypeSignature[]) value);
176-
lowerBounds = value;
177-
}
178-
return (Type[]) value.clone();
179-
}
180112
}
181113

182114
class WildcardTypeImplUpperBoundsComputer implements RecomputeFieldValue.CustomFieldValueComputer {
@@ -203,21 +135,6 @@ public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original,
203135
}
204136
}
205137

206-
final class Util_sun_reflect_generics_reflectiveObjects_WildcardTypeImpl {
207-
208-
/** Emulate the Java class hierarchy. */
209-
@SuppressFBWarnings(value = "BC", justification = "Widening cast between @TargetClasses")
210-
static Target_sun_reflect_generics_reflectiveObjects_LazyReflectiveObjectGenerator asLazyReflectiveObjectGenerator(
211-
Target_sun_reflect_generics_reflectiveObjects_WildcardTypeImpl wildCardTypeImpl) {
212-
return Target_sun_reflect_generics_reflectiveObjects_LazyReflectiveObjectGenerator.class.cast(wildCardTypeImpl);
213-
}
214-
215-
/** Emulate virtual dispatch. */
216-
static Type[] reifyBounds(Target_sun_reflect_generics_reflectiveObjects_WildcardTypeImpl wildCardTypeImpl, FieldTypeSignature[] boundASTs) {
217-
return asLazyReflectiveObjectGenerator(wildCardTypeImpl).reifyBounds(boundASTs);
218-
}
219-
}
220-
221138
class GuardedBoundsAccess {
222139

223140
static Type[] getLowerBounds(WildcardTypeImpl receiver) {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/ReadableJavaField.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ static JavaConstant readFieldValue(MetaAccessProvider metaAccess, ConstantReflec
3535
if (javaField instanceof ReadableJavaField) {
3636
ReadableJavaField readableField = (ReadableJavaField) javaField;
3737
if (!readableField.isValueAvailable()) {
38+
assert !readableField.allowConstantFolding() && readableField.isUnknown();
3839
return SubstrateObjectConstant.forObject(null);
3940
}
4041
return readableField.readValue(metaAccess, javaConstant);
@@ -64,4 +65,8 @@ static boolean injectFinalForRuntimeCompilation(ResolvedJavaField original) {
6465
return false;
6566
}
6667
}
68+
69+
default boolean isUnknown() {
70+
return false;
71+
}
6772
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ private Map<String, Long> calculateHeapBreakdown(Collection<ObjectInfo> heapObje
505505
}
506506
long metadataByteLength = ImageSingletons.lookup(ReflectionMetadataDecoder.class).getMetadataByteLength();
507507
if (metadataByteLength > 0) {
508-
classNameToSize.put(BREAKDOWN_BYTE_ARRAY_PREFIX + linkStrategy.asDocLink("reflection metadata", "#glossary-method-metadata"), metadataByteLength);
508+
classNameToSize.put(BREAKDOWN_BYTE_ARRAY_PREFIX + linkStrategy.asDocLink("reflection metadata", "#glossary-reflection-metadata"), metadataByteLength);
509509
remainingBytes -= metadataByteLength;
510510
}
511511
if (graphEncodingByteLength > 0) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageHeapScanner.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package com.oracle.svm.hosted.heap;
2626

2727
import java.lang.reflect.AccessibleObject;
28+
import java.lang.reflect.Executable;
2829
import java.lang.reflect.Field;
2930
import java.util.function.Consumer;
3031

@@ -60,6 +61,7 @@ public class SVMImageHeapScanner extends ImageHeapScanner {
6061
private final Class<?> economicMapImpl;
6162
private final Field economicMapImplEntriesField;
6263
private final Field economicMapImplHashArrayField;
64+
private final RuntimeReflectionSupport reflectionSupport;
6365

6466
public SVMImageHeapScanner(ImageHeap imageHeap, ImageClassLoader loader, AnalysisMetaAccess metaAccess,
6567
SnippetReflectionProvider snippetReflection, ConstantReflectionProvider aConstantReflection, ObjectScanningObserver aScanningObserver) {
@@ -69,6 +71,7 @@ public SVMImageHeapScanner(ImageHeap imageHeap, ImageClassLoader loader, Analysi
6971
economicMapImplEntriesField = ReflectionUtil.lookupField(economicMapImpl, "entries");
7072
economicMapImplHashArrayField = ReflectionUtil.lookupField(economicMapImpl, "hashArray");
7173
ImageSingletons.add(ImageHeapScanner.class, this);
74+
reflectionSupport = ImageSingletons.lookup(RuntimeReflectionSupport.class);
7275
}
7376

7477
public static ImageHeapScanner instance() {
@@ -143,8 +146,8 @@ protected void onObjectReachable(ImageHeapObject imageHeapObject) {
143146
super.onObjectReachable(imageHeapObject);
144147

145148
Object object = SubstrateObjectConstant.asObject(imageHeapObject.getObject());
146-
if (object instanceof AccessibleObject) {
147-
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerHeapReflectionObject((AccessibleObject) object);
149+
if (object instanceof Field || object instanceof Executable) {
150+
reflectionSupport.registerHeapReflectionObject((AccessibleObject) object);
148151
}
149152
}
150153
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueComputer;
5454
import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueProvider;
5555
import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueTransformer;
56+
import com.oracle.svm.core.annotate.UnknownObjectField;
57+
import com.oracle.svm.core.annotate.UnknownPrimitiveField;
5658
import com.oracle.svm.core.config.ConfigurationValues;
5759
import com.oracle.svm.core.meta.ReadableJavaField;
5860
import com.oracle.svm.core.util.UserError;
@@ -499,4 +501,9 @@ public String toString() {
499501
public Field getJavaField() {
500502
return OriginalFieldProvider.getJavaField(GraalAccess.getOriginalSnippetReflection(), original);
501503
}
504+
505+
@Override
506+
public boolean isUnknown() {
507+
return annotated.isAnnotationPresent(UnknownObjectField.class) || annotated.isAnnotationPresent(UnknownPrimitiveField.class);
508+
}
502509
}

0 commit comments

Comments
 (0)