Skip to content
Open
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
67 changes: 63 additions & 4 deletions src/main/java/org/mikeneck/graalvm/config/ClassUsage.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,26 @@ public class ClassUsage implements Comparable<ClassUsage>, MergeableConfig<Class
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean allPublicClasses;

@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean queryAllDeclaredConstructors;

@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean queryAllPublicConstructors;

@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean queryAllDeclaredMethods;

@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
public Boolean queryAllPublicMethods;

@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
public SortedSet<MethodUsage> queriedMethods = Collections.emptySortedSet();

@SuppressWarnings("unused")
public ClassUsage() {}

Expand All @@ -71,7 +91,12 @@ private ClassUsage(
@Nullable Boolean allPublicConstructors,
@Nullable Boolean allPublicFields,
@Nullable Boolean allDeclaredClasses,
@Nullable Boolean allPublicClasses) {
@Nullable Boolean allPublicClasses,
@Nullable Boolean queryAllDeclaredConstructors,
@Nullable Boolean queryAllPublicConstructors,
@Nullable Boolean queryAllDeclaredMethods,
@Nullable Boolean queryAllPublicMethods,
@Nullable SortedSet<MethodUsage> queriedMethods) {
this.name = name;
this.methods = methods;
this.fields = fields;
Expand All @@ -83,6 +108,11 @@ private ClassUsage(
this.allPublicFields = allPublicFields;
this.allDeclaredClasses = allDeclaredClasses;
this.allPublicClasses = allPublicClasses;
this.queryAllDeclaredConstructors = queryAllDeclaredConstructors;
this.queryAllPublicConstructors = queryAllPublicConstructors;
this.queryAllDeclaredMethods = queryAllDeclaredMethods;
this.queryAllPublicMethods = queryAllPublicMethods;
this.queriedMethods = queriedMethods;
}

public ClassUsage(
Expand Down Expand Up @@ -180,7 +210,12 @@ public boolean equals(Object o) {
&& Objects.equals(allPublicConstructors, that.allPublicConstructors)
&& Objects.equals(allPublicFields, that.allPublicFields)
&& Objects.equals(allDeclaredClasses, that.allDeclaredClasses)
&& Objects.equals(allPublicClasses, that.allPublicClasses);
&& Objects.equals(allPublicClasses, that.allPublicClasses)
&& Objects.equals(queryAllDeclaredConstructors, that.queryAllDeclaredConstructors)
&& Objects.equals(queryAllPublicConstructors, that.queryAllPublicConstructors)
&& Objects.equals(queryAllDeclaredMethods, that.queryAllDeclaredMethods)
&& Objects.equals(queryAllPublicMethods, that.queryAllPublicMethods)
&& Objects.equals(queriedMethods, that.queriedMethods);
}

@Override
Expand All @@ -196,7 +231,12 @@ public int hashCode() {
allPublicConstructors,
allPublicFields,
allDeclaredClasses,
allPublicClasses);
allPublicClasses,
queryAllDeclaredConstructors,
queryAllPublicConstructors,
queryAllDeclaredMethods,
queryAllPublicMethods,
queriedMethods);
}

@SuppressWarnings("StringBufferReplaceableByString")
Expand All @@ -214,6 +254,11 @@ public String toString() {
sb.append(", allPublicFields=").append(allPublicFields);
sb.append(", allDeclaredClasses=").append(allDeclaredClasses);
sb.append(", allPublicClasses=").append(allPublicClasses);
sb.append(", queryAllDeclaredConstructors=").append(queryAllDeclaredConstructors);
sb.append(", queryAllPublicConstructors=").append(queryAllPublicConstructors);
sb.append(", queryAllDeclaredMethods=").append(queryAllDeclaredMethods);
sb.append(", queryAllPublicMethods=").append(queryAllPublicMethods);
sb.append(", queriedMethods=").append(queriedMethods);
sb.append('}');
return sb.toString();
}
Expand All @@ -232,6 +277,13 @@ public ClassUsage mergeWith(ClassUsage other) {
TreeSet<MethodUsage> newMethods = new TreeSet<>(this.methods);
newMethods.addAll(other.methods);
FieldUsages newFields = this.fields.mergeWith(other.fields);
TreeSet<MethodUsage> newQueriedMethods = new TreeSet<>();
if (this.queriedMethods != null) {
newQueriedMethods.addAll(this.queriedMethods);
}
if (other.queriedMethods != null) {
newQueriedMethods.addAll(other.queriedMethods);
}
return new ClassUsage(
this.name,
newMethods,
Expand All @@ -243,6 +295,13 @@ public ClassUsage mergeWith(ClassUsage other) {
BooleanMergeable.mergeBoolean(this.allPublicConstructors, other.allPublicConstructors),
BooleanMergeable.mergeBoolean(this.allPublicFields, other.allPublicFields),
BooleanMergeable.mergeBoolean(this.allDeclaredClasses, other.allDeclaredClasses),
BooleanMergeable.mergeBoolean(this.allPublicClasses, other.allPublicClasses));
BooleanMergeable.mergeBoolean(this.allPublicClasses, other.allPublicClasses),
BooleanMergeable.mergeBoolean(
this.queryAllDeclaredConstructors, other.queryAllDeclaredConstructors),
BooleanMergeable.mergeBoolean(
this.queryAllPublicConstructors, other.queryAllPublicConstructors),
BooleanMergeable.mergeBoolean(this.queryAllDeclaredMethods, other.queryAllDeclaredMethods),
BooleanMergeable.mergeBoolean(this.queryAllPublicMethods, other.queryAllPublicMethods),
newQueriedMethods);
}
}
36 changes: 36 additions & 0 deletions src/main/java/org/mikeneck/graalvm/config/ProxyUsage.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package org.mikeneck.graalvm.config;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.TreeSet;
import org.jetbrains.annotations.NotNull;

@JsonDeserialize(using = ProxyUsage.ProxyUsageDeserializer.class)
public class ProxyUsage extends TreeSet<String> implements Comparable<ProxyUsage> {

public ProxyUsage() {
Expand Down Expand Up @@ -45,4 +54,31 @@ public int compareTo(@NotNull ProxyUsage o) {
}
return thatIterator.hasNext() ? -1 : 0;
}

static class ProxyUsageDeserializer extends JsonDeserializer {
private final ObjectMapper mapper = new ObjectMapper();

@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String[] interfaces =
mapper
.readerForListOf(String.class)
.readValue(findArray(p.getCodec().readTree(p)), String[].class);
return new ProxyUsage(interfaces);
}

private ArrayNode findArray(TreeNode tree) {
if (tree.isArray()) {
return (ArrayNode) tree;
}
if (tree.isObject()) {
// new format from GraalVM 21.3.0
TreeNode interfaces = tree.get("interfaces");
if (interfaces != null && interfaces.isArray()) {
return (ArrayNode) interfaces;
}
}
throw new IllegalArgumentException();
}
}
}
10 changes: 10 additions & 0 deletions src/test/java/org/mikeneck/graalvm/config/ProxyConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,14 @@ void emptyMergedWithEmptyBecomesEmpty() {

assertThat(proxyConfig).isEqualTo(Collections.emptySortedSet());
}

/** GraalVM 21.3.0 generates proxy-config in new format */
@Test
void graal213() throws IOException {
try (InputStream inputStream = reader.configJsonResource("config/proxy-config-4.json")) {
ProxyConfig proxyConfig = objectMapper.readValue(inputStream, ProxyConfig.class);
assertThat(proxyConfig)
.contains(new ProxyUsage("com.example.Printer", "com.example.ExitCode"));
}
}
}
26 changes: 21 additions & 5 deletions src/test/java/org/mikeneck/graalvm/config/ReflectConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DynamicTest;
Expand Down Expand Up @@ -276,4 +272,24 @@ Iterable<DynamicTest> case111() throws IOException {
return tests;
}
}

/**
* GraalVM 21.3.0 added the {@code queriedMethods} field into the class usage
*
* @see <a
* href="https://medium.com/graalvm/graalvm-21-3-is-here-java-17-native-image-performance-updates-and-more-ac4cbafcfc05"
* >Official example config file</a>
*/
@Test
void graal213() throws IOException {
ClassUsage expected = new ClassUsage("org.graalvm.Example");
expected.queryAllDeclaredConstructors = true;
expected.queriedMethods = new TreeSet<>();
expected.queriedMethods.add(new MethodUsage("queriedOnlyMethod"));

try (InputStream inputStream = reader.configJsonResource("config/reflect-config-3.json")) {
ReflectConfig reflectConfig = objectMapper.readValue(inputStream, ReflectConfig.class);
assertThat(reflectConfig).contains(expected);
}
}
}
5 changes: 5 additions & 0 deletions src/test/resources/config/proxy-config-4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[
{
"interfaces":["com.example.Printer","com.example.ExitCode"]}

]
5 changes: 5 additions & 0 deletions src/test/resources/config/reflect-config-3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[{
"name": "org.graalvm.Example",
"queryAllDeclaredConstructors": true,
"queriedMethods": [{"name":"queriedOnlyMethod", "parameterTypes":[]}]
}]