Skip to content

Commit c3519c8

Browse files
committed
Introduce a typeReached check for Class.forName
1 parent 6393391 commit c3519c8

File tree

37 files changed

+661
-226
lines changed

37 files changed

+661
-226
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.nodes.spi;
26+
27+
import jdk.vm.ci.meta.ResolvedJavaType;
28+
29+
/**
30+
* Used to determine if <code>EnsureClassInitializedNode</code> is required for type-reached
31+
* checking.
32+
*/
33+
public interface TypeReachedProvider {
34+
/**
35+
* Check whether {@param type} needs a class-initialization node to mark it as reached.
36+
*/
37+
boolean initializationCheckRequired(ResolvedJavaType type);
38+
}

docs/reference-manual/native-image/assets/config-condition-schema-v1.0.0.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44
"title": "JSON schema for the conditions used in GraalVM Native Image configuration files",
55
"properties": {
66
"typeReachable": {
7-
"type": "string",
7+
"deprecated": true,
8+
"$ref": "config-type-schema-v1.0.0.json",
89
"title": "Fully qualified name of a class that must be reachable in order to register the type <type> for reflection"
10+
},
11+
"typeReached": {
12+
"$ref": "config-type-schema-v1.0.0.json",
13+
"title": "Fully qualified name of a class that must be reached in order to register the type <type> for reflection"
914
}
1015
},
11-
"required": [
12-
"typeReachable"
16+
"oneOf": [
17+
"typeReachable",
18+
"typeReached"
1319
],
1420
"additionalProperties": false,
1521
"type": "object"

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ConfigurationCondition.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,43 +43,51 @@
4343
import java.util.Objects;
4444

4545
/**
46-
* A condition that describes if a reflectively accessed element in Native Image is visible by the
46+
* A condition that describes if a reflectively-accessed element in Native Image is visible by the
4747
* user.
4848
* <p>
49-
* Currently, there is only one type of condition (<code>typeReached</code>) so this is a single
49+
* Currently, there is only one type of condition (<code>typeReached</code>) so this is a final
5050
* class instead of the class hierarchy. The {@link ConfigurationCondition#type} represents the
5151
* {@link Class<>} that needs to be reached by analysis in order for an element to be visible.
5252
*/
5353
public final class ConfigurationCondition {
5454

5555
/* Cached to save space: it is used as a marker for all non-conditional elements */
56-
private static final ConfigurationCondition JAVA_LANG_OBJECT_REACHED = new ConfigurationCondition(Object.class);
56+
private static final ConfigurationCondition JAVA_LANG_OBJECT_REACHED = new ConfigurationCondition(Object.class, true);
5757

5858
public static ConfigurationCondition alwaysTrue() {
5959
return JAVA_LANG_OBJECT_REACHED;
6060
}
6161

6262
private final Class<?> type;
6363

64-
public static ConfigurationCondition create(Class<?> type) {
64+
private final boolean runtimeChecked;
65+
66+
public static ConfigurationCondition create(Class<?> type, boolean runtimeChecked) {
67+
Objects.requireNonNull(type);
6568
if (JAVA_LANG_OBJECT_REACHED.getType().equals(type)) {
6669
return JAVA_LANG_OBJECT_REACHED;
6770
}
68-
return new ConfigurationCondition(type);
71+
return new ConfigurationCondition(type, runtimeChecked);
6972
}
7073

7174
public boolean isAlwaysTrue() {
7275
return ConfigurationCondition.alwaysTrue().equals(this);
7376
}
7477

75-
private ConfigurationCondition(Class<?> type) {
78+
private ConfigurationCondition(Class<?> type, boolean runtimeChecked) {
79+
this.runtimeChecked = runtimeChecked;
7680
this.type = type;
7781
}
7882

7983
public Class<?> getType() {
8084
return type;
8185
}
8286

87+
public boolean isRuntimeChecked() {
88+
return runtimeChecked;
89+
}
90+
8391
@Override
8492
public boolean equals(Object o) {
8593
if (this == o) {
@@ -88,13 +96,13 @@ public boolean equals(Object o) {
8896
if (o == null || getClass() != o.getClass()) {
8997
return false;
9098
}
91-
ConfigurationCondition condition = (ConfigurationCondition) o;
92-
return Objects.equals(type, condition.type);
99+
ConfigurationCondition that = (ConfigurationCondition) o;
100+
return runtimeChecked == that.runtimeChecked && Objects.equals(type, that.type);
93101
}
94102

95103
@Override
96104
public int hashCode() {
97-
return Objects.hash(type);
105+
return Objects.hash(type, runtimeChecked);
98106
}
99107

100108
}

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/UnresolvedConfigurationCondition.java

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,27 @@
4343
import java.util.Objects;
4444

4545
/**
46-
* This is an unresolved version of the {@link ConfigurationCondition} used only during parsing.
46+
* Represents a {@link ConfigurationCondition} during parsing before it is resolved by in a context
47+
* of the classpath.
4748
*/
48-
public class UnresolvedConfigurationCondition implements Comparable<UnresolvedConfigurationCondition> {
49+
public final class UnresolvedConfigurationCondition implements Comparable<UnresolvedConfigurationCondition> {
50+
private static final UnresolvedConfigurationCondition JAVA_LANG_OBJECT_REACHED = new UnresolvedConfigurationCondition(Object.class.getTypeName(), true);
51+
public static final String TYPE_REACHED_KEY = "typeReached";
52+
public static final String TYPE_REACHABLE_KEY = "typeReachable";
4953
private final String typeName;
50-
private static final UnresolvedConfigurationCondition JAVA_LANG_OBJECT_REACHED = new UnresolvedConfigurationCondition(Object.class.getTypeName());
54+
private final boolean runtimeChecked;
5155

52-
public static UnresolvedConfigurationCondition create(String typeName) {
56+
public static UnresolvedConfigurationCondition create(String typeName, boolean runtimeChecked) {
5357
Objects.requireNonNull(typeName);
5458
if (JAVA_LANG_OBJECT_REACHED.getTypeName().equals(typeName)) {
5559
return JAVA_LANG_OBJECT_REACHED;
5660
}
57-
return new UnresolvedConfigurationCondition(typeName);
61+
return new UnresolvedConfigurationCondition(typeName, runtimeChecked);
5862
}
5963

60-
protected UnresolvedConfigurationCondition(String typeName) {
64+
private UnresolvedConfigurationCondition(String typeName, boolean runtimeChecked) {
6165
this.typeName = typeName;
66+
this.runtimeChecked = runtimeChecked;
6267
}
6368

6469
public static UnresolvedConfigurationCondition alwaysTrue() {
@@ -69,6 +74,14 @@ public String getTypeName() {
6974
return typeName;
7075
}
7176

77+
public boolean isRuntimeChecked() {
78+
return runtimeChecked;
79+
}
80+
81+
public boolean isAlwaysTrue() {
82+
return typeName.equals(JAVA_LANG_OBJECT_REACHED.getTypeName());
83+
}
84+
7285
@Override
7386
public boolean equals(Object o) {
7487
if (this == o) {
@@ -77,26 +90,28 @@ public boolean equals(Object o) {
7790
if (o == null || getClass() != o.getClass()) {
7891
return false;
7992
}
80-
UnresolvedConfigurationCondition condition = (UnresolvedConfigurationCondition) o;
81-
return Objects.equals(typeName, condition.typeName);
93+
UnresolvedConfigurationCondition that = (UnresolvedConfigurationCondition) o;
94+
return runtimeChecked == that.runtimeChecked && Objects.equals(typeName, that.typeName);
8295
}
8396

8497
@Override
8598
public int hashCode() {
86-
return Objects.hash(typeName);
99+
return Objects.hash(typeName, runtimeChecked);
87100
}
88101

89102
@Override
90-
public String toString() {
91-
return "[\"typeReachable\": \"" + typeName + "\"" + "]";
103+
public int compareTo(UnresolvedConfigurationCondition o) {
104+
int res = Boolean.compare(runtimeChecked, o.runtimeChecked);
105+
if (res != 0) {
106+
return res;
107+
}
108+
return typeName.compareTo(o.typeName);
92109
}
93110

94111
@Override
95-
public int compareTo(UnresolvedConfigurationCondition c) {
96-
return this.typeName.compareTo(c.typeName);
112+
public String toString() {
113+
var field = runtimeChecked ? TYPE_REACHED_KEY : TYPE_REACHABLE_KEY;
114+
return "[" + field + ": \"" + typeName + "\"" + "]";
97115
}
98116

99-
public boolean isAlwaysTrue() {
100-
return typeName.equals(JAVA_LANG_OBJECT_REACHED.getTypeName());
101-
}
102117
}

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ConfigurationConditionPrintable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
package com.oracle.svm.configure.config;
2626

2727
import static com.oracle.svm.core.configure.ConfigurationParser.CONDITIONAL_KEY;
28-
import static com.oracle.svm.core.configure.ConfigurationParser.TYPE_REACHABLE_KEY;
28+
import static org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition.TYPE_REACHABLE_KEY;
2929

3030
import java.io.IOException;
3131

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/conditional/ConditionalConfigurationComputer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private ConfigurationSet deduceConditionalConfiguration(Map<MethodInfo, List<Met
171171
for (List<MethodCallNode> value : methodCallNodes.values()) {
172172
for (MethodCallNode node : value) {
173173
String className = node.methodInfo.getJavaDeclaringClassName();
174-
UnresolvedConfigurationCondition condition = UnresolvedConfigurationCondition.create(className);
174+
UnresolvedConfigurationCondition condition = UnresolvedConfigurationCondition.create(className, false);
175175
var resolveCondition = ConfigurationConditionResolver.identityResolver().resolveCondition(condition);
176176
addConfigurationWithCondition(configurationSet, node.configuration, resolveCondition.get());
177177
}

0 commit comments

Comments
 (0)