Skip to content
Merged
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 @@ -120,7 +120,11 @@ public static String findStableLambdaName(ClassInitializationPlugin cip, Provide

public static boolean isLambdaType(ResolvedJavaType type) {
String typeName = type.getName();
return type.isFinalFlagSet() && typeName.contains(LAMBDA_CLASS_NAME_SUBSTRING) && lambdaMatcher(type.getName()).find();
return type.isFinalFlagSet() && isLambdaName(typeName);
}

public static boolean isLambdaName(String name) {
return name.contains(LAMBDA_CLASS_NAME_SUBSTRING) && lambdaMatcher(name).find();
}

private static String createStableLambdaName(ResolvedJavaType lambdaType, List<ResolvedJavaMethod> targetMethods) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ public static boolean check(InvocationPlugins plugins, Type declaringType, Invoc
}
klass = klass.getSuperclass();
}
throw new AssertionError(format("graph builder plugin for %s not found", plugin.getMethodNameWithArgumentsDescriptor()));
throw new AssertionError(format("graph builder plugin for %s not found. check that the plugin-method signature matches the target", plugin.getMethodNameWithArgumentsDescriptor()));
}

static boolean checkResolvable(Type declaringType, InvocationPlugin plugin) {
Expand Down
52 changes: 43 additions & 9 deletions docs/reference-manual/native-image/ReachabilityMetadata.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

---
layout: ni-docs
toc_group: metadata
Expand Down Expand Up @@ -328,13 +329,37 @@ Metadata for dynamic proxies is provided in `proxy-config.json` files.

## Serialization
Java can serialize any class that implements the `Serializable` interface.
Serialization usually requires reflectively accessing the class of the object being serialized.
The JDK also requires additional information about the class to serialize its object.
Native Image supports serialization with proper metadata.
Native Image supports serialization with proper serializaiton metadata registration. This is necessary as serialization usually
requires reflectively accessing the class of the object that is being serialized.

### Serialization Metadata In Code
### Serialization Metadata Registration In Code

It is not possible to register classes used for serialization in code.
Native Image detects calls to `ObjectInputFilter.Config#createFilter(String pattern)` and if the `pattern` argument is constant, the exact classes mentioned in the pattern will be registered for serialization.
For example, the following pattern will register the class `pkg.SerializableClass` for serialization:
```java
var filter = ObjectInputFilter.Config.createFilter("pkg.SerializableClass;!*;")
objectInputStream.setObjectInputFilter(proof);
```
Using this pattern has a positive side effect of improving security on the JVM as only `pkg.SerializableClass` can be received by the
`objectInputStream`.

Wildcard patterns do the serialization registration only for lambda-proxy classes of an enclosing class. For example, to register lambda serialization in an enclosing class `pkg.LambdaHolder` use:
```java
ObjectInputFilter.Config.createFilter("pkg.LambdaHolder$$Lambda$*;")
```

Patterns like `"pkg.**"` and `"pkg.Prefix*"` will not perform serialization registration as they are too general and would increase image size significantly.

For calls to the `sun.reflect.ReflectionFactory#newConstructorForSerialization(java.lang.Class)` and `sun.reflect.ReflectionFactory#newConstructorForSerialization(java.lang.Class, )` native image detects calls to these functions when all arguments and the receiver are constant. For example, the following call will register `SerializlableClass` for serialization:
```java
ReflectionFactory.getReflectionFactory().newConstructorForSerialization(SerializableClass.class);
```
To create a custom constructor for serialization use:
```java
var constructor = SuperSuperClass.class.getDeclaredConstructor();
var newConstructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(BaseClass.class, constructor);
```
Proxy classes can only be registered for serialization via the JSON files.

### Serialization Metadata in JSON
Metadata for serialization is provided in `serialization-config.json` files.
Expand All @@ -354,16 +379,25 @@ Metadata for serialization is provided in `serialization-config.json` files.
"condition": {
"typeReachable": "<condition-class>"
},
"name": "<fully-qualified-class-name>",
"customTargetConstructorClass": "<custom-target-constructor-class>"
"name": "<fully-qualified-class-name>"
}
]
],
"proxies": [
{
"condition": {
"typeReachable": "<condition-class>"
},
"interfaces": ["<fully-qualified-interface-name-1>", "<fully-qualified-interface-name-n>"]
}
]
}
```

Each entry in `types` enables serializing and deserializing objects of the class given by `name`.

Lambda serialization is also supported: all lambdas declared in the methods of the class given by `name` can be serialized/deserialized.
Each entry in `lambdaCapturingTypes` enables lambda serialization: all lambdas declared in the methods of the class given by `name` can be serialized and deserialized.

Each entry in `proxies` enables the [Proxy](https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html) serialization by providing an interface list that a proxy implements.

## Predefined Classes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@

public class Scalafmt {

private static final String file =
"/* __ *\\\n" +
private static final String file = "/* __ *\\\n" +
"** ________ ___ / / ___ Scala API **\n" +
"** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **\n" +
"** __\\ \\/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@

@State(Scope.Benchmark)
public class Geom {
@Param("1000")
static int geomCnt;
@Param("1000") static int geomCnt;
private static Geobject[] samples;

@Setup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ public static void init() {
Random random = new Random(42);
for (int i = 0; i < PERSONS_NR; i++) {
persons[i] = new Person(
random.nextDouble() >= EMPLOYMENT_RATIO ? Employment.EMPLOYED : Employment.UNEMPLOYED,
random.nextInt(MAX_SALARY),
random.nextInt(MAX_AGE));
random.nextDouble() >= EMPLOYMENT_RATIO ? Employment.EMPLOYED : Employment.UNEMPLOYED,
random.nextInt(MAX_SALARY),
random.nextInt(MAX_AGE));
}
}

@Benchmark
public static double bench() {
return Arrays.stream(persons).filter(p -> p.getEmployment() == Employment.EMPLOYED)
.filter(p -> p.getSalary() > 100_000)
.mapToInt(Person::getAge).filter(age -> age >= 40).average().getAsDouble();
return Arrays.stream(persons).filter(p -> p.getEmployment() == Employment.EMPLOYED).filter(p -> p.getSalary() > 100_000).mapToInt(Person::getAge).filter(
age -> age >= 40).average().getAsDouble();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,20 @@
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


@State(Scope.Benchmark)
public class BinaryTrees {

private static final int MIN_DEPTH = 4;

@Param("14")
private static int binaryTreesN;
@Param("14") private static int binaryTreesN;

@Benchmark
public static void bench(Blackhole blackhole) throws Exception {

final int maxDepth = binaryTreesN < (MIN_DEPTH + 2) ? MIN_DEPTH + 2 : binaryTreesN;
final int stretchDepth = maxDepth + 1;

blackhole.consume("stretch tree of depth " + stretchDepth + "\t check: "
+ bottomUpTree(stretchDepth).itemCheck());
blackhole.consume("stretch tree of depth " + stretchDepth + "\t check: " + bottomUpTree(stretchDepth).itemCheck());

final TreeNode longLivedTree = bottomUpTree(maxDepth);

Expand All @@ -104,21 +101,19 @@ public static void bench(Blackhole blackhole) throws Exception {
final TreeNode treeNode1 = bottomUpTree(depth);
check += treeNode1.itemCheck();
}
results[(depth - MIN_DEPTH) / 2] =
iterations + "\t trees of depth " + depth + "\t check: " + check;
results[(depth - MIN_DEPTH) / 2] = iterations + "\t trees of depth " + depth + "\t check: " + check;
});
}

executorService.shutdown();
executorService.awaitTermination(120L, TimeUnit.SECONDS);


for (final String str : results) {
blackhole.consume(str);
}

blackhole.consume("long lived tree of depth " + maxDepth +
"\t check: " + longLivedTree.itemCheck());
"\t check: " + longLivedTree.itemCheck());
}

private static TreeNode bottomUpTree(final int depth) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@
@State(Scope.Benchmark)
public class ChameneosRedux {

@Param("20000")
static int chameneosReduxN;
@Param("20000") static int chameneosReduxN;

static {

Expand All @@ -81,10 +80,7 @@ public class ChameneosRedux {
Colour.YELLOW.setColours(Colour.RED, Colour.BLUE, Colour.YELLOW);
}

private static Phaser startMeeting(final boolean isFirst
, final int n
, final Blackhole blackhole
, final Colour... colours) {
private static Phaser startMeeting(final boolean isFirst, final int n, final Blackhole blackhole, final Colour... colours) {
final int len = colours.length;
final MeetingPlace place = new MeetingPlace(n);
final Creature[] creatures = new Creature[len];
Expand All @@ -99,21 +95,16 @@ private static Phaser startMeeting(final boolean isFirst

@Benchmark
public static void bench(Blackhole blackhole) {
//int n = 20000;
// int n = 20000;

startMeeting(true, chameneosReduxN, blackhole, Colour.BLUE, Colour.RED, Colour.YELLOW);
Phaser phaser = startMeeting(false, chameneosReduxN, blackhole, Colour.BLUE, Colour.RED, Colour.YELLOW,
Colour.RED, Colour.YELLOW, Colour.BLUE, Colour.RED,
Colour.YELLOW, Colour.RED, Colour.BLUE);
Colour.RED, Colour.YELLOW, Colour.BLUE, Colour.RED,
Colour.YELLOW, Colour.RED, Colour.BLUE);
for (final Colour c1 : Colour.values()) {
for (final Colour c2 : Colour.values()) {
StringBuilder sb = new StringBuilder();
sb.append(c1.toString())
.append(" + ")
.append(c2.toString())
.append(" -> ")
.append(c1.complement(c2).toString())
.append('\n');
sb.append(c1.toString()).append(" + ").append(c2.toString()).append(" -> ").append(c1.complement(c2).toString()).append('\n');
blackhole.consume(sb.toString());
}
}
Expand Down Expand Up @@ -205,9 +196,7 @@ static final class Creature extends Thread {
private int count = 0;
private int sameCount = 0;

public Creature(final MeetingPlace place
, final Colour colour
, final Phaser phaser) {
public Creature(final MeetingPlace place, final Colour colour, final Phaser phaser) {
this.place = place;
this.phaser = phaser;
exchange.id = System.identityHashCode(this);
Expand All @@ -218,7 +207,7 @@ public Creature(final MeetingPlace place
public void run() {
CreatureExchange otherCreature;

for (; ; ) {
for (;;) {
otherCreature = place.meet(exchange);
if (otherCreature == null) {
phaser.arrive();
Expand All @@ -244,8 +233,8 @@ public int getSameCount() {
final static class CreaturePhaser extends Phaser {

static final String[] NUMBERS = {
"zero", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine"
"zero", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine"
};
static final Object lock = new Object();
static boolean firstHasNotFinished = true;
Expand All @@ -254,11 +243,7 @@ final static class CreaturePhaser extends Phaser {
final Creature[] creatures;
final Blackhole blackhole;

public CreaturePhaser(final boolean isFirst
, final Colour[] colours
, final Creature[] creatures
, final int phases
, final Blackhole blackhole) {
public CreaturePhaser(final boolean isFirst, final Colour[] colours, final Creature[] creatures, final int phases, final Blackhole blackhole) {
super(phases);
this.isFirst = isFirst;
this.colours = colours;
Expand All @@ -267,8 +252,7 @@ public CreaturePhaser(final boolean isFirst
}

@Override
protected boolean onAdvance(final int phase
, final int registeredParties) {
protected boolean onAdvance(final int phase, final int registeredParties) {
synchronized (lock) {
if (!isFirst) {
while (firstHasNotFinished) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
* Contributed by Oleg Mazurov, June 2010
*/


import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
Expand All @@ -71,8 +70,7 @@
public class FannkuchRedux {

private static final int NCHUNKS = 150;
@Param("9")
private static int fannkuchReduxN;
@Param("9") private static int fannkuchReduxN;
private static int CHUNKSZ;
private static int NTASKS;
private static int[] Fact;
Expand Down Expand Up @@ -191,7 +189,7 @@ void runTask(int task) {

int maxflips = 1;
int chksum = 0;
for (int i = idxMin; ; ) {
for (int i = idxMin;;) {

if (p[0] != 0) {
int flips = countFlips();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ public class Mandelbrot {
static double[] Crb;
static double[] Cib;

@Param("500")
static int mandelbrotN;
@Param("500") static int mandelbrotN;

static int getByte(int x, int y) {
int res = 0;
Expand All @@ -107,11 +106,13 @@ static int getByte(int x, int y) {

if (Zr1 * Zr1 + Zi1 * Zi1 > 4) {
b |= 2;
if (b == 3) break;
if (b == 3)
break;
}
if (Zr2 * Zr2 + Zi2 * Zi2 > 4) {
b |= 1;
if (b == 3) break;
if (b == 3)
break;
}
} while (--j > 0);
res = (res << 2) + b;
Expand Down
Loading