Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ public final class DynamicHubCompanion {
*/
final int classFileAccessFlags;

/** The class that serves as the host for the nest. All nestmates have the same host. */
final Class<?> nestHost;
/**
* The class that serves as the host for the nest. All nestmates have the same host. Always
* encoded with null for Dynamic hubs allocated at runtime.
*/
@Stable Class<?> nestHost;

/** The simple binary name of this class, as returned by {@code Class.getSimpleBinaryName0}. */
final String simpleBinaryName;
Expand Down Expand Up @@ -126,11 +129,11 @@ public final class DynamicHubCompanion {
* Metadata for querying the reflection data. When using layered images this field is always
* null and should not be queried. Instead, use {@link LayeredReflectionMetadataSingleton}.
*/
@UnknownObjectField(canBeNull = true, availability = BuildPhaseProvider.AfterCompilation.class) //
@Stable DynamicHub.ReflectionMetadata reflectionMetadata;
@UnknownObjectField(canBeNull = true, types = ImageReflectionMetadata.class, availability = BuildPhaseProvider.AfterCompilation.class) //
@Stable ReflectionMetadata reflectionMetadata;

@UnknownObjectField(canBeNull = true, availability = BuildPhaseProvider.AfterCompilation.class) //
@Stable DynamicHub.DynamicHubMetadata hubMetadata;
@UnknownObjectField(canBeNull = true, types = ImageDynamicHubMetadata.class, availability = BuildPhaseProvider.AfterCompilation.class) //
@Stable DynamicHubMetadata hubMetadata;

/**
* Classloader used for loading this class. Most classes have the correct class loader set
Expand Down Expand Up @@ -159,9 +162,9 @@ static DynamicHubCompanion createHosted(Module module, DynamicHub superHub, Stri
}

static DynamicHubCompanion createAtRuntime(Module module, DynamicHub superHub, String sourceFileName, int modifiers, int classFileAccessFlags,
ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
ClassLoader classLoader, String simpleBinaryName, Object declaringClass, String signature) {
assert RuntimeClassLoading.isSupported();
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classFileAccessFlags, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classFileAccessFlags, classLoader, null, simpleBinaryName, declaringClass, signature);
}

private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers, int classFileAccessFlags,
Expand All @@ -178,4 +181,12 @@ private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFil

this.classLoader = classLoader;
}

public void setHubMetadata(RuntimeDynamicHubMetadata hubMetadata) {
this.hubMetadata = hubMetadata;
}

public void setReflectionMetadata(RuntimeReflectionMetadata reflectionMetadata) {
this.reflectionMetadata = reflectionMetadata;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.oracle.svm.core.hub;

interface DynamicHubMetadata {

Object[] getEnclosingMethod(DynamicHub declaringClass);

Object[] getSigners(DynamicHub declaringClass);

byte[] getRawAnnotations(DynamicHub declaringClass);

byte[] getRawTypeAnnotations(DynamicHub declaringClass);

Class<?>[] getDeclaredClasses(DynamicHub declaringClass);

Class<?>[] getNestMembers(DynamicHub declaringClass);

Class<?>[] getPermittedSubClasses(DynamicHub declaringClass);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.hub;

import com.oracle.svm.core.BuildPhaseProvider;
import com.oracle.svm.core.heap.UnknownPrimitiveField;
import com.oracle.svm.core.reflect.RuntimeMetadataDecoder;
import org.graalvm.nativeimage.ImageSingletons;

import static com.oracle.svm.core.reflect.RuntimeMetadataDecoder.NO_DATA;

final class ImageDynamicHubMetadata implements DynamicHubMetadata {
@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class) //
final int enclosingMethodInfoIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int annotationsIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int typeAnnotationsIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int classesEncodingIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int permittedSubclassesEncodingIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int nestMembersEncodingIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int signersEncodingIndex;

ImageDynamicHubMetadata(int enclosingMethodInfoIndex, int annotationsIndex, int typeAnnotationsIndex, int classesEncodingIndex, int permittedSubclassesEncodingIndex,
int nestMembersEncodingIndex, int signersEncodingIndex) {
this.enclosingMethodInfoIndex = enclosingMethodInfoIndex;
this.annotationsIndex = annotationsIndex;
this.typeAnnotationsIndex = typeAnnotationsIndex;
this.classesEncodingIndex = classesEncodingIndex;
this.permittedSubclassesEncodingIndex = permittedSubclassesEncodingIndex;
this.nestMembersEncodingIndex = nestMembersEncodingIndex;
this.signersEncodingIndex = signersEncodingIndex;
}

@Override
public Object[] getEnclosingMethod(DynamicHub declaringClass) {
if (enclosingMethodInfoIndex == NO_DATA) {
return null;
}
Object[] enclosingMethod = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseEnclosingMethod(enclosingMethodInfoIndex, declaringClass);
if (enclosingMethod != null) {
PredefinedClassesSupport.throwIfUnresolvable((Class<?>) enclosingMethod[0], declaringClass.getClassLoader0());
}
return enclosingMethod;
}

@Override
public Object[] getSigners(DynamicHub declaringClass) {
if (signersEncodingIndex == NO_DATA) {
return null;
}
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseObjects(signersEncodingIndex, declaringClass);
}

@Override
public byte[] getRawAnnotations(DynamicHub declaringClass) {
if (annotationsIndex == NO_DATA) {
return null;
}
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(annotationsIndex, declaringClass);
}

@Override
public byte[] getRawTypeAnnotations(DynamicHub declaringClass) {
if (typeAnnotationsIndex == NO_DATA) {
return null;
}
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(typeAnnotationsIndex, declaringClass);
}

@Override
public Class<?>[] getDeclaredClasses(DynamicHub declaringClass) {
if (classesEncodingIndex == NO_DATA) {
return new Class<?>[0];
}
Class<?>[] declaredClasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(classesEncodingIndex, declaringClass);
for (Class<?> clazz : declaredClasses) {
PredefinedClassesSupport.throwIfUnresolvable(clazz, declaringClass.getClassLoader0());
}
return declaredClasses;
}

@Override
public Class<?>[] getNestMembers(DynamicHub declaringClass) {
if (nestMembersEncodingIndex == NO_DATA) {
return new Class<?>[]{DynamicHub.toClass(declaringClass)};
}
Class<?>[] nestMembers = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(nestMembersEncodingIndex, declaringClass);
for (Class<?> clazz : nestMembers) {
PredefinedClassesSupport.throwIfUnresolvable(clazz, declaringClass.getClassLoader0());
}
return nestMembers;
}

@Override
public Class<?>[] getPermittedSubClasses(DynamicHub declaringClass) {
if (permittedSubclassesEncodingIndex == NO_DATA) {
return new Class<?>[0];
}
Class<?>[] permittedSubclasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(permittedSubclassesEncodingIndex, declaringClass);
for (Class<?> clazz : permittedSubclasses) {
PredefinedClassesSupport.throwIfUnresolvable(clazz, declaringClass.getClassLoader0());
}
return permittedSubclasses;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.hub;

import com.oracle.svm.core.BuildPhaseProvider;
import com.oracle.svm.core.heap.UnknownPrimitiveField;
import com.oracle.svm.core.reflect.RuntimeMetadataDecoder;
import org.graalvm.nativeimage.ImageSingletons;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.RecordComponent;

import static com.oracle.svm.core.reflect.RuntimeMetadataDecoder.NO_DATA;

/**
* Instances of this class are used to represent the reflection metadata for Dynamic hubs prepared
* at build time and included in the image. For dynamic hubs loaded dynamically at runtime
* {@link RuntimeReflectionMetadata} is used.
*/
public final class ImageReflectionMetadata implements ReflectionMetadata {
@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int fieldsEncodingIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int methodsEncodingIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int constructorsEncodingIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int recordComponentsEncodingIndex;

@UnknownPrimitiveField(availability = BuildPhaseProvider.CompileQueueFinished.class)//
final int classFlags;

ImageReflectionMetadata(int fieldsEncodingIndex, int methodsEncodingIndex, int constructorsEncodingIndex, int recordComponentsEncodingIndex, int classFlags) {
this.fieldsEncodingIndex = fieldsEncodingIndex;
this.methodsEncodingIndex = methodsEncodingIndex;
this.constructorsEncodingIndex = constructorsEncodingIndex;
this.recordComponentsEncodingIndex = recordComponentsEncodingIndex;
this.classFlags = classFlags;
}

public int getClassFlags() {
return classFlags;
}

@Override
public Field[] getDeclaredFields(DynamicHub declaringClass, boolean publicOnly, int layerNum) {
if (fieldsEncodingIndex == NO_DATA) {
return new Field[0];
}
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseFields(declaringClass, fieldsEncodingIndex, publicOnly, layerNum);
}

@Override
public Method[] getDeclaredMethods(DynamicHub declaringClass, boolean publicOnly, int layerNum) {
if (methodsEncodingIndex == NO_DATA) {
return new Method[0];
}
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseMethods(declaringClass, methodsEncodingIndex, publicOnly, layerNum);
}

@Override
public Constructor<?>[] getDeclaredConstructors(DynamicHub declaringClass, boolean publicOnly, int layerNum) {
if (constructorsEncodingIndex == NO_DATA) {
return new Constructor<?>[0];
}
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseConstructors(declaringClass, constructorsEncodingIndex, publicOnly, layerNum);
}

@Override
public RecordComponent[] getRecordComponents(DynamicHub declaringClass, int layerNum) {
if (recordComponentsEncodingIndex == NO_DATA) {
/* See ReflectionDataBuilder.buildRecordComponents() for details. */
throw DynamicHub.recordsNotAvailable(declaringClass);
}
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseRecordComponents(declaringClass, recordComponentsEncodingIndex, layerNum);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.hub.DynamicHub.ReflectionMetadata;
import com.oracle.svm.core.imagelayer.BuildingInitialLayerPredicate;
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader;
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
Expand All @@ -53,7 +52,7 @@ public class LayeredReflectionMetadataSingleton implements MultiLayeredImageSing
private static final String LAYERED_REFLECTION_METADATA_HUBS = "layered reflection metadata hubs";
private static final String LAYERED_REFLECTION_METADATA_CLASS_FLAGS = "layered reflection metadata classFlags";

private final EconomicMap<Integer, ReflectionMetadata> reflectionMetadataMap = EconomicMap.create();
private final EconomicMap<Integer, ImageReflectionMetadata> reflectionMetadataMap = EconomicMap.create();

/**
* The class flags registered in previous layers. This map is used to check if the class flags
Expand Down Expand Up @@ -83,7 +82,7 @@ public static LayeredReflectionMetadataSingleton[] singletons() {
}

@Platforms(Platform.HOSTED_ONLY.class)
public void setReflectionMetadata(DynamicHub hub, ReflectionMetadata reflectionMetadata) {
public void setReflectionMetadata(DynamicHub hub, ImageReflectionMetadata reflectionMetadata) {
/* GR-63472: Two different classes could have the same name in different class loaders */
assert !reflectionMetadataMap.containsKey(hub.getTypeID()) : "The hub %s was added twice in the same layered reflection metadata".formatted(hub);
if (isClassFlagsSubsetOfPreviousLayer(hub.getTypeID(), reflectionMetadata) && isReflectionMetadataEmpty(reflectionMetadata)) {
Expand All @@ -98,15 +97,15 @@ private boolean isClassFlagsSubsetOfPreviousLayer(int hub, ReflectionMetadata re
}

private static int getCombinedClassFlags(ReflectionMetadata reflectionMetadata, int previousLayerFlags) {
return previousLayerFlags | reflectionMetadata.classFlags;
return previousLayerFlags | reflectionMetadata.getClassFlags();
}

private static boolean isReflectionMetadataEmpty(ReflectionMetadata reflectionMetadata) {
private static boolean isReflectionMetadataEmpty(ImageReflectionMetadata reflectionMetadata) {
return reflectionMetadata.fieldsEncodingIndex == -1 && reflectionMetadata.methodsEncodingIndex == -1 &&
reflectionMetadata.constructorsEncodingIndex == -1 && reflectionMetadata.recordComponentsEncodingIndex == -1;
}

public ReflectionMetadata getReflectionMetadata(DynamicHub hub) {
public ImageReflectionMetadata getReflectionMetadata(DynamicHub hub) {
return reflectionMetadataMap.get(hub.getTypeID());
}

Expand Down
Loading