Skip to content

Commit

Permalink
Better reflection filtering algorithm
Browse files Browse the repository at this point in the history
This reduces the size from 270m to 48m

Only include reflection data for types with runtime retained
annotations, excluding several which don't have a high correlation
with reflective use (e.g. Deprecated, Documetned).
  • Loading branch information
carterkozak committed Jan 5, 2021
1 parent 176301e commit 2748e37
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.palantir.conjure.parser.types;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.palantir.parsec.ParseException;

/**
Expand All @@ -25,6 +26,7 @@ public interface ConjureType {

<T> T visit(ConjureTypeVisitor<T> visitor);

@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
static ConjureType fromString(String value) throws ParseException {
return TypeParser.INSTANCE.parse(value);
}
Expand Down
1 change: 1 addition & 0 deletions conjure/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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")) {
Expand Down Expand Up @@ -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<Annotation> filter) {
Expand Down Expand Up @@ -159,4 +171,27 @@ private static boolean isAnnotated(AnnotatedElement element, Predicate<Annotatio
}
return false;
}

private enum RuntimeAnnotationFilter implements Predicate<Annotation> {
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.");
}
}
}

0 comments on commit 2748e37

Please sign in to comment.