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
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ public void addObject(T object) {
entry.frequency++;
}

/**
* Returns whether the given object has been previously added to the array.
*/
public boolean contains(T object) {
if (object == null && containsNull) {
return true;
}
Entry<T> entry = map.get(object);
return entry != null;
}

/**
* Returns the index of an object in the array. The object must have been
* {@link #addObject(Object) added} before.
Expand Down
1 change: 1 addition & 0 deletions sdk/src/org.graalvm.nativeimage/snapshot.sigtest
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,7 @@ meth public !varargs static void register(boolean,java.lang.reflect.Field[])
anno 0 java.lang.Deprecated()
meth public !varargs static void register(java.lang.Class<?>[])
meth public !varargs static void register(java.lang.reflect.Executable[])
meth public !varargs static void registerAsQueried(java.lang.reflect.Executable[])
meth public !varargs static void register(java.lang.reflect.Field[])
meth public !varargs static void registerForReflectiveInstantiation(java.lang.Class<?>[])
supr java.lang.Object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,19 @@ public static void register(Class<?>... classes) {
* @since 19.0
*/
public static void register(Executable... methods) {
ImageSingletons.lookup(RuntimeReflectionSupport.class).register(ConfigurationCondition.alwaysTrue(), methods);
ImageSingletons.lookup(RuntimeReflectionSupport.class).register(ConfigurationCondition.alwaysTrue(), false, methods);
}

/**
* Makes the provided methods available for reflection queries at run time. The methods will be
* returned by {@link Class#getMethod}, {@link Class#getMethods}, and all the other methods on
* {@link Class} that return a single or a list of methods, but will not be invocable and will
* not be considered reachable.
*
* @since 21.3
*/
public static void registerAsQueried(Executable... methods) {
ImageSingletons.lookup(RuntimeReflectionSupport.class).register(ConfigurationCondition.alwaysTrue(), true, methods);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
public interface ReflectionRegistry {
void register(ConfigurationCondition condition, Class<?>... classes);

void register(ConfigurationCondition condition, Executable... methods);
void register(ConfigurationCondition condition, boolean queriedOnly, Executable... methods);

void register(ConfigurationCondition condition, boolean finalIsWritable, Field... fields);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
*/
package org.graalvm.nativeimage.impl;

import java.lang.reflect.Executable;
import java.util.Set;

public interface RuntimeReflectionSupport extends ReflectionRegistry {
// specific to java.lang.reflect reflection
Set<Executable> getQueriedOnlyMethods();
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,44 @@ static Executable getJavaMethod(SnippetReflectionProvider reflectionProvider, Re
return ((OriginalMethodProvider) method).getJavaMethod();
}
try {
ResolvedJavaMethod.Parameter[] parameters = method.getParameters();
Class<?>[] parameterTypes = new Class<?>[parameters.length];
ResolvedJavaType declaringClassType = method.getDeclaringClass();
for (int i = 0; i < parameterTypes.length; i++) {
parameterTypes[i] = OriginalClassProvider.getJavaClass(reflectionProvider, parameters[i].getType().resolve(declaringClassType));
}
Class<?> declaringClass = OriginalClassProvider.getJavaClass(reflectionProvider, declaringClassType);
if (method.isConstructor()) {
return declaringClass.getDeclaredConstructor(parameterTypes);
} else {
return declaringClass.getDeclaredMethod(method.getName(), parameterTypes);
}
return getJavaMethodInternal(reflectionProvider, method);
} catch (NoSuchMethodException e) {
throw AnalysisError.shouldNotReachHere();
}
}

static boolean hasJavaMethod(SnippetReflectionProvider reflectionProvider, ResolvedJavaMethod method) {
if (method instanceof OriginalMethodProvider) {
return ((OriginalMethodProvider) method).hasJavaMethod();
}
try {
getJavaMethodInternal(reflectionProvider, method);
return true;
} catch (NoSuchMethodException | LinkageError | RuntimeException e) {
/*
* These exceptions may happen anytime during the lookup, so we can't simply use the
* result of getJavaMethodInternal.
*/
return false;
}
}

static Executable getJavaMethodInternal(SnippetReflectionProvider reflectionProvider, ResolvedJavaMethod method) throws NoSuchMethodException {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these lookups are getting more and more important, we need to make it more robust eventually by looking directly into the HotSpot JVMCI method. I experimented with that a while ago: https://github.com/christianwimmer/graal/blob/ReachabilityAnalysis/compiler/src/org.graalvm.reachability/src/org/graalvm/reachability/ReachabilityAnalysis.java#L1128

ResolvedJavaMethod.Parameter[] parameters = method.getParameters();
Class<?>[] parameterTypes = new Class<?>[parameters.length];
ResolvedJavaType declaringClassType = method.getDeclaringClass();
for (int i = 0; i < parameterTypes.length; i++) {
parameterTypes[i] = OriginalClassProvider.getJavaClass(reflectionProvider, parameters[i].getType().resolve(declaringClassType));
}
Class<?> declaringClass = OriginalClassProvider.getJavaClass(reflectionProvider, declaringClassType);
if (method.isConstructor()) {
return declaringClass.getDeclaredConstructor(parameterTypes);
} else {
return declaringClass.getDeclaredMethod(method.getName(), parameterTypes);
}
}

Executable getJavaMethod();

boolean hasJavaMethod();
}
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,11 @@ public Executable getJavaMethod() {
return OriginalMethodProvider.getJavaMethod(universe.getOriginalSnippetReflection(), wrapped);
}

@Override
public boolean hasJavaMethod() {
return OriginalMethodProvider.hasJavaMethod(universe.getOriginalSnippetReflection(), wrapped);
}

/**
* Unique, per method, context insensitive invoke. The context insensitive invoke uses the
* receiver type of the method, i.e., its declaring class. Therefore this invoke will link with
Expand Down
Loading