Skip to content
Closed
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 @@ -4,12 +4,18 @@
"title": "JSON schema for the conditions used in GraalVM Native Image configuration files",
"properties": {
"typeReachable": {
"type": "string",
"deprecated": true,
"$ref": "config-type-schema-v1.0.0.json",
"title": "Fully qualified name of a class that must be reachable in order to register the type <type> for reflection"
},
"typeReached": {
"$ref": "config-type-schema-v1.0.0.json",
"title": "Fully qualified name of a class that must be reached in order to register the type <type> for reflection"
}
},
"required": [
"typeReachable"
"oneOf": [
"typeReachable",
"typeReached"
],
"additionalProperties": false,
"type": "object"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,43 +43,51 @@
import java.util.Objects;

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

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

public static ConfigurationCondition alwaysTrue() {
return JAVA_LANG_OBJECT_REACHED;
}

private final Class<?> type;

public static ConfigurationCondition create(Class<?> type) {
private final boolean runtimeChecked;

public static ConfigurationCondition create(Class<?> type, boolean runtimeChecked) {
Objects.requireNonNull(type);
if (JAVA_LANG_OBJECT_REACHED.getType().equals(type)) {
return JAVA_LANG_OBJECT_REACHED;
}
return new ConfigurationCondition(type);
return new ConfigurationCondition(type, runtimeChecked);
}

public boolean isAlwaysTrue() {
return ConfigurationCondition.alwaysTrue().equals(this);
}

private ConfigurationCondition(Class<?> type) {
private ConfigurationCondition(Class<?> type, boolean runtimeChecked) {
this.runtimeChecked = runtimeChecked;
this.type = type;
}

public Class<?> getType() {
return type;
}

public boolean isRuntimeChecked() {
return runtimeChecked;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -88,13 +96,13 @@ public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
ConfigurationCondition condition = (ConfigurationCondition) o;
return Objects.equals(type, condition.type);
ConfigurationCondition that = (ConfigurationCondition) o;
return runtimeChecked == that.runtimeChecked && Objects.equals(type, that.type);
}

@Override
public int hashCode() {
return Objects.hash(type);
return Objects.hash(type, runtimeChecked);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,27 @@
import java.util.Objects;

/**
* This is an unresolved version of the {@link ConfigurationCondition} used only during parsing.
* Represents a {@link ConfigurationCondition} during parsing before it is resolved in a context of
* the classpath.
*/
public class UnresolvedConfigurationCondition implements Comparable<UnresolvedConfigurationCondition> {
public final class UnresolvedConfigurationCondition implements Comparable<UnresolvedConfigurationCondition> {
private static final UnresolvedConfigurationCondition JAVA_LANG_OBJECT_REACHED = new UnresolvedConfigurationCondition(Object.class.getTypeName(), true);
public static final String TYPE_REACHED_KEY = "typeReached";
public static final String TYPE_REACHABLE_KEY = "typeReachable";
private final String typeName;
private static final UnresolvedConfigurationCondition JAVA_LANG_OBJECT_REACHED = new UnresolvedConfigurationCondition(Object.class.getTypeName());
private final boolean runtimeChecked;

public static UnresolvedConfigurationCondition create(String typeName) {
public static UnresolvedConfigurationCondition create(String typeName, boolean runtimeChecked) {
Objects.requireNonNull(typeName);
if (JAVA_LANG_OBJECT_REACHED.getTypeName().equals(typeName)) {
return JAVA_LANG_OBJECT_REACHED;
}
return new UnresolvedConfigurationCondition(typeName);
return new UnresolvedConfigurationCondition(typeName, runtimeChecked);
}

protected UnresolvedConfigurationCondition(String typeName) {
private UnresolvedConfigurationCondition(String typeName, boolean runtimeChecked) {
this.typeName = typeName;
this.runtimeChecked = runtimeChecked;
}

public static UnresolvedConfigurationCondition alwaysTrue() {
Expand All @@ -69,6 +74,14 @@ public String getTypeName() {
return typeName;
}

public boolean isRuntimeChecked() {
return runtimeChecked;
}

public boolean isAlwaysTrue() {
return typeName.equals(JAVA_LANG_OBJECT_REACHED.getTypeName());
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -77,26 +90,28 @@ public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
UnresolvedConfigurationCondition condition = (UnresolvedConfigurationCondition) o;
return Objects.equals(typeName, condition.typeName);
UnresolvedConfigurationCondition that = (UnresolvedConfigurationCondition) o;
return runtimeChecked == that.runtimeChecked && Objects.equals(typeName, that.typeName);
}

@Override
public int hashCode() {
return Objects.hash(typeName);
return Objects.hash(typeName, runtimeChecked);
}

@Override
public String toString() {
return "[\"typeReachable\": \"" + typeName + "\"" + "]";
public int compareTo(UnresolvedConfigurationCondition o) {
int res = Boolean.compare(runtimeChecked, o.runtimeChecked);
if (res != 0) {
return res;
}
return typeName.compareTo(o.typeName);
}

@Override
public int compareTo(UnresolvedConfigurationCondition c) {
return this.typeName.compareTo(c.typeName);
public String toString() {
var field = runtimeChecked ? TYPE_REACHED_KEY : TYPE_REACHABLE_KEY;
return "[" + field + ": \"" + typeName + "\"" + "]";
}

public boolean isAlwaysTrue() {
return typeName.equals(JAVA_LANG_OBJECT_REACHED.getTypeName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
package com.oracle.svm.configure.config;

import static com.oracle.svm.core.configure.ConfigurationParser.CONDITIONAL_KEY;
import static com.oracle.svm.core.configure.ConfigurationParser.TYPE_REACHABLE_KEY;
import static org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition.TYPE_REACHABLE_KEY;

import java.io.IOException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private ConfigurationSet deduceConditionalConfiguration(Map<MethodInfo, List<Met
for (List<MethodCallNode> value : methodCallNodes.values()) {
for (MethodCallNode node : value) {
String className = node.methodInfo.getJavaDeclaringClassName();
UnresolvedConfigurationCondition condition = UnresolvedConfigurationCondition.create(className);
UnresolvedConfigurationCondition condition = UnresolvedConfigurationCondition.create(className, false);
var resolveCondition = ConfigurationConditionResolver.identityResolver().resolveCondition(condition);
addConfigurationWithCondition(configurationSet, node.configuration, resolveCondition.get());
}
Expand Down
Loading