Skip to content

Commit 5afb1b5

Browse files
committed
Throw missing reflection registration errors
1 parent 0b4640a commit 5afb1b5

36 files changed

+1804
-454
lines changed

sdk/src/org.graalvm.nativeimage/snapshot.sigtest

+34
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ meth public static <%0 extends java.lang.Enum<{%%0}>> {%%0} valueOf(java.lang.Cl
3737
supr java.lang.Object
3838
hfds name,ordinal
3939

40+
CLSS public java.lang.Error
41+
cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean)
42+
cons public init()
43+
cons public init(java.lang.String)
44+
cons public init(java.lang.String,java.lang.Throwable)
45+
cons public init(java.lang.Throwable)
46+
supr java.lang.Throwable
47+
hfds serialVersionUID
48+
4049
CLSS public java.lang.Exception
4150
cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean)
4251
cons public init()
@@ -222,6 +231,15 @@ meth public abstract void fatalError()
222231
meth public abstract void flush()
223232
meth public abstract void log(org.graalvm.nativeimage.c.type.CCharPointer,org.graalvm.word.UnsignedWord)
224233

234+
CLSS public final org.graalvm.nativeimage.MissingReflectionRegistrationError
235+
cons public init(java.lang.String,java.lang.Class<?>,java.lang.Class<?>,java.lang.String,java.lang.Class<?>[])
236+
meth public java.lang.Class<?> getElementType()
237+
meth public java.lang.Class<?> getDeclaringClass()
238+
meth public java.lang.String getElementName()
239+
meth public java.lang.Class<?>[] getParameterTypes()
240+
supr java.lang.Error
241+
hfds serialVersionUID
242+
225243
CLSS public abstract interface org.graalvm.nativeimage.ObjectHandle
226244
intf org.graalvm.word.ComparableWord
227245

@@ -1075,10 +1093,26 @@ meth public !varargs static void register(boolean,boolean,java.lang.reflect.Fiel
10751093
meth public !varargs static void register(boolean,java.lang.reflect.Field[])
10761094
anno 0 java.lang.Deprecated(boolean forRemoval=false, java.lang.String since="21.1")
10771095
meth public !varargs static void register(java.lang.Class<?>[])
1096+
meth public static void registerClassLookup(java.lang.String)
10781097
meth public !varargs static void register(java.lang.reflect.Executable[])
1098+
meth public !varargs static void registerMethodLookup(java.lang.Class<?>,java.lang.String,java.lang.Class<?>[])
1099+
meth public !varargs static void registerConstructorLookup(java.lang.Class<?>,java.lang.Class<?>[])
10791100
meth public !varargs static void register(java.lang.reflect.Field[])
1101+
meth public static void registerFieldLookup(java.lang.Class<?>,java.lang.String)
10801102
meth public !varargs static void registerAsQueried(java.lang.reflect.Executable[])
10811103
meth public !varargs static void registerForReflectiveInstantiation(java.lang.Class<?>[])
1104+
meth public static void registerAllClasses(java.lang.Class<?>)
1105+
meth public static void registerAllDeclaredClasses(java.lang.Class<?>)
1106+
meth public static void registerAllConstructors(java.lang.Class<?>)
1107+
meth public static void registerAllDeclaredConstructors(java.lang.Class<?>)
1108+
meth public static void registerAllFields(java.lang.Class<?>)
1109+
meth public static void registerAllDeclaredFields(java.lang.Class<?>)
1110+
meth public static void registerAllMethods(java.lang.Class<?>)
1111+
meth public static void registerAllDeclaredMethods(java.lang.Class<?>)
1112+
meth public static void registerAllNestMembers(java.lang.Class<?>)
1113+
meth public static void registerAllPermittedSubclasses(java.lang.Class<?>)
1114+
meth public static void registerAllRecordComponents(java.lang.Class<?>)
1115+
meth public static void registerAllSigners(java.lang.Class<?>)
10821116
supr java.lang.Object
10831117

10841118
CLSS public final org.graalvm.nativeimage.hosted.RuntimeResourceAccess
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package org.graalvm.nativeimage;
42+
43+
import java.io.Serial;
44+
import java.lang.reflect.Constructor;
45+
import java.lang.reflect.Field;
46+
import java.lang.reflect.Method;
47+
48+
/**
49+
* This exception is thrown when a reflective query (such as
50+
* {@link Class#getMethod(String, Class[])}) tries to access an element that was not <a href=
51+
* "https://www.graalvm.org/latest/reference-manual/native-image/metadata/#reflection">registered
52+
* for reflection</a> in the program. When an element is not registered, the exception will be
53+
* thrown both for elements that exist and elements that do not exist on the given classpath.
54+
* <p/>
55+
* The purpose of this exception is to easily discover unregistered elements and to assure that all
56+
* reflective operations for registered elements have the expected behaviour.
57+
* <p/>
58+
* We distinguish between two types of reflective queries: bulk queries and individual queries.
59+
* <ol>
60+
* <li>Bulk queries are methods like {@link Class#getFields()} which return a complete list of
61+
* corresponding elements. Those queries need to be explicitly registered for reflection in order to
62+
* be called. If that is not the case, a {@link MissingReflectionRegistrationError} will be
63+
* thrown.</li>
64+
* <li>Individual queries are methods like {@link Class#getField(String)} which return a single
65+
* element. Those queries will succeed (or throw the expected {@link ReflectiveOperationException}
66+
* if either the element was individually registered for reflection, or the corresponding bulk query
67+
* was registered for reflection. If that is not the case, a
68+
* {@link MissingReflectionRegistrationError} will be thrown. Some individual queries, like
69+
* {@link Class#forName(String)}, do not have a corresponding bulk query and as such need their
70+
* arguments to be individually registered for reflection in order to behave correctly.</li>
71+
* </ol>
72+
* Examples:
73+
* <p/>
74+
* Registration: {@code "queryAllDeclaredMethods": true}<br>
75+
* {@code declaringClass.getDeclaredMethods()} will succeed.<br>
76+
* {@code declaringClass.getDeclaredMethod("existingMethod")} will return the expected method.<br>
77+
* {@code declaringClass.getDeclaredMethod("nonexistentMethod")} will throw a
78+
* {@link NoSuchMethodException}.
79+
* <p/>
80+
* Registration: {@code "fields": [{"name": "registeredField"}, {"name":
81+
* "registeredNonexistentField"}]}<br>
82+
* {@code declaringClass.getDeclaredFields()} will throw a
83+
* {@link MissingReflectionRegistrationError}.<br>
84+
* {@code declaringClass.getField("registeredField")} will return the expected field.<br>
85+
* {@code declaringClass.getField("registeredNonexistentField")} will throw a
86+
* {@link NoSuchFieldException}.<br>
87+
* {@code declaringClass.getField("unregisteredField")} will throw a
88+
* {@link MissingReflectionRegistrationError}.<br>
89+
* {@code declaringClass.getField("unregisteredNonexistentField")} will throw a
90+
* {@link MissingReflectionRegistrationError}.<br>
91+
*/
92+
public final class MissingReflectionRegistrationError extends Error {
93+
@Serial private static final long serialVersionUID = 2764341882856270640L;
94+
95+
private final Class<?> elementType;
96+
97+
private final Class<?> declaringClass;
98+
99+
private final String elementName;
100+
101+
private final Class<?>[] parameterTypes;
102+
103+
public MissingReflectionRegistrationError(String message, Class<?> elementType, Class<?> declaringClass, String elementName, Class<?>[] parameterTypes) {
104+
super(message);
105+
this.elementType = elementType;
106+
this.declaringClass = declaringClass;
107+
this.elementName = elementName;
108+
this.parameterTypes = parameterTypes;
109+
}
110+
111+
/**
112+
* @return The type of the element trying to be queried ({@link Class}, {@link Method},
113+
* {@link Field} or {@link Constructor}), or null if the query is a bulk query (like
114+
* {@link Class#getMethods()}).
115+
*/
116+
public Class<?> getElementType() {
117+
return elementType;
118+
}
119+
120+
/**
121+
* @return The class on which the missing query was tried, or null on static queries (e.g.
122+
* {@link Class#forName(String)}).
123+
*/
124+
public Class<?> getDeclaringClass() {
125+
return declaringClass;
126+
}
127+
128+
/**
129+
* @return The name of the queried element, or bulk query method (e.g. {@code "getMethods"}).
130+
*/
131+
public String getElementName() {
132+
return elementName;
133+
}
134+
135+
/**
136+
* @return The parameter types passed to the query, or null if the query doesn't take parameter
137+
* types as argument.
138+
*/
139+
public Class<?>[] getParameterTypes() {
140+
return parameterTypes;
141+
}
142+
}

0 commit comments

Comments
 (0)