diff --git a/conjure-core/src/main/java/com/palantir/conjure/parser/types/ConjureType.java b/conjure-core/src/main/java/com/palantir/conjure/parser/types/ConjureType.java index d6cbb17c8..cca60fbe9 100644 --- a/conjure-core/src/main/java/com/palantir/conjure/parser/types/ConjureType.java +++ b/conjure-core/src/main/java/com/palantir/conjure/parser/types/ConjureType.java @@ -16,6 +16,7 @@ package com.palantir.conjure.parser.types; +import com.fasterxml.jackson.annotation.JsonCreator; import com.palantir.parsec.ParseException; /** @@ -25,6 +26,7 @@ public interface ConjureType { T visit(ConjureTypeVisitor visitor); + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) static ConjureType fromString(String value) throws ParseException { return TypeParser.INSTANCE.parse(value); } diff --git a/conjure/build.gradle b/conjure/build.gradle index 9bda06fc8..89925d8e2 100644 --- a/conjure/build.gradle +++ b/conjure/build.gradle @@ -47,6 +47,7 @@ graal { // Fail if a native image cannot be created. Otherwise a fallback image which relies // on a hotspot jdk is required. option '--no-fallback' + option '--static' // Missing classes result in runtime failures rather than compile time. Many libraries // have optional dependencies that may be excluded. Take the log4j-core disruptor // dependency for example. diff --git a/conjure/src/main/java/com/palantir/conjure/cli/RuntimeReflectionRegistrationFeature.java b/conjure/src/main/java/com/palantir/conjure/cli/RuntimeReflectionRegistrationFeature.java index 0b1c35cf2..e2d81f448 100644 --- a/conjure/src/main/java/com/palantir/conjure/cli/RuntimeReflectionRegistrationFeature.java +++ b/conjure/src/main/java/com/palantir/conjure/cli/RuntimeReflectionRegistrationFeature.java @@ -27,11 +27,16 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; @@ -44,13 +49,20 @@ final class RuntimeReflectionRegistrationFeature implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { // Common standard library classes - maybeRegisterClassForReflection(String.class); - maybeRegisterClassForReflection(HashSet.class); - maybeRegisterClassForReflection(HashMap.class); - maybeRegisterClassForReflection(LinkedHashMap.class); - maybeRegisterClassForReflection(ArrayList.class); - maybeRegisterClassForReflection(LinkedList.class); - maybeRegisterClassForReflection(ConcurrentHashMap.class); + registerClassForReflection(String.class); + registerClassForReflection(HashSet.class); + registerClassForReflection(LinkedHashSet.class); + registerClassForReflection(HashMap.class); + registerClassForReflection(LinkedHashMap.class); + registerClassForReflection(ArrayList.class); + registerClassForReflection(LinkedList.class); + registerClassForReflection(ConcurrentHashMap.class); + try { + registerClassForReflection(com.fasterxml.jackson.databind.ext.Java7Handlers.class); + registerClassForReflection(com.fasterxml.jackson.databind.ext.Java7HandlersImpl.class); + } catch (Throwable t) { + t.printStackTrace(); + } for (Path jarPath : access.getApplicationClassPath()) { String jarFileName = jarPath.getFileName().toString(); if (!jarFileName.endsWith(".jar")) { @@ -128,7 +140,7 @@ private static boolean isAnyElementGraalAnnotated(Class clazz) { } private static boolean isAnyElementRuntimeAnnotated(Class clazz) { - return isAnyElementAnnotated(clazz, _any -> true); + return isAnyElementAnnotated(clazz, RuntimeAnnotationFilter.INSTANCE); } private static boolean isAnyElementAnnotated(Class clazz, Predicate filter) { @@ -159,4 +171,27 @@ private static boolean isAnnotated(AnnotatedElement element, Predicate { + INSTANCE; + + @Override + public boolean test(Annotation annotation) { + // javax nullness. Are these used for validation at runtime? + if (annotation instanceof Nullable + || annotation instanceof ParametersAreNonnullByDefault + || annotation instanceof Nonnull + || annotation instanceof CheckReturnValue) { + // Deprecation annotations are common and provide little signal. + return false; + } + String name = annotation.annotationType().getName(); + // Errorprone annotations are used at compile time, not runtime + return !name.startsWith("com.google.") + && !name.startsWith("org.checkerframework") + // Deprecated, Documented, Target, Retention, FunctionalInterface, + // SafeVarargs, Inherited, Repeatable + && !name.startsWith("java.lang."); + } + } }