Skip to content

Commit baf5656

Browse files
committed
New type for serialization added. Fixed issues that made benchmark fail.
1 parent a7afd92 commit baf5656

File tree

11 files changed

+210
-65
lines changed

11 files changed

+210
-65
lines changed

compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LambdaUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
public final class LambdaUtils {
5252
private static final Pattern LAMBDA_PATTERN = Pattern.compile("\\$\\$Lambda\\$\\d+[/\\.][^/]+;");
5353
private static final char[] HEX = "0123456789abcdef".toCharArray();
54-
public static final String SPLIT_BY_LAMBDA = "\\$\\$Lambda\\$";
55-
public static final String LAMBDA_FUNCTIONS_NAME_PATTERN = "$$Lambda$";
54+
public static final String LAMBDA_SPLIT_PATTERN = "\\$\\$Lambda\\$";
55+
public static final String LAMBDA_CLASS_NAME_PATTERN = "$$Lambda$";
5656

5757
private static GraphBuilderConfiguration buildLambdaParserConfig(ClassInitializationPlugin cip) {
5858
GraphBuilderConfiguration.Plugins plugins = new GraphBuilderConfiguration.Plugins(new InvocationPlugins());
@@ -109,7 +109,7 @@ public static String findStableLambdaName(ClassInitializationPlugin cip, Provide
109109

110110
public static boolean isLambdaType(ResolvedJavaType type) {
111111
String typeName = type.getName();
112-
return type.isFinalFlagSet() && typeName.contains("/") && typeName.contains(LAMBDA_FUNCTIONS_NAME_PATTERN) && lambdaMatcher(type.getName()).find();
112+
return type.isFinalFlagSet() && typeName.contains("/") && typeName.contains(LAMBDA_CLASS_NAME_PATTERN) && lambdaMatcher(type.getName()).find();
113113
}
114114

115115
private static String createStableLambdaName(ResolvedJavaType lambdaType, List<ResolvedJavaMethod> targetMethods) {

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeSerializationSupport.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ public interface RuntimeSerializationSupport {
4848

4949
void registerWithTargetConstructorClass(ConfigurationCondition condition, String className, String customTargetConstructorClassName);
5050

51+
void registerLambdaCapturingClass(ConfigurationCondition condition, String lambdaCapturingClassName);
5152
}

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -976,11 +976,12 @@ private static JNIObjectHandle shouldIncludeMethod(JNIEnvironment jni, JNIObject
976976
return result;
977977
}
978978

979-
/*
979+
/**
980980
* We have to find a class that captures a lambda function so it can be registered by the agent.
981-
* We have to get SerializedLambda instance first. After that we get lambda capturing class from
982-
* that instance using JNIHandleSet#getFieldId to get field id and JNIObjectHandle#invoke on to
983-
* get that field value. We get name of the capturing class and tell the agent to register it.
981+
* We have to get a SerializedLambda instance first. After that we get a lambda capturing class
982+
* from that instance using JNIHandleSet#getFieldId to get field id and JNIObjectHandle#invoke
983+
* on to get that field value. We get a name of the capturing class and tell the agent to
984+
* register it.
984985
*/
985986
private static boolean registerCapturingClass(JNIEnvironment jni, Breakpoint bp, InterceptedState state) {
986987
JNIObjectHandle serializedLambdaInstance = getObjectArgument(0);
@@ -1003,7 +1004,7 @@ private static boolean registerCapturingClass(JNIEnvironment jni, Breakpoint bp,
10031004
validObjectStreamClassInstance,
10041005
state.getFullStackTraceOrNull(),
10051006
/*- String serializationTargetClass, String customTargetConstructorClass */
1006-
capturingClassName, null);
1007+
capturingClassName);
10071008

10081009
guarantee(!testException(jni));
10091010
}
@@ -1029,7 +1030,6 @@ private static boolean objectStreamClassConstructor(JNIEnvironment jni, Breakpoi
10291030
* additional ObjectStreamClass instances (usually the super classes) are created
10301031
* recursively. Call ObjectStreamClass.getClassDataLayout0() can get all of them.
10311032
*/
1032-
10331033
JNIMethodId getClassDataLayout0MId = agent.handles().getJavaIoObjectStreamClassGetClassDataLayout0(jni, bp.clazz);
10341034
JNIObjectHandle dataLayoutArray = callObjectMethod(jni, objectStreamClassInstance, getClassDataLayout0MId);
10351035

@@ -1055,7 +1055,6 @@ private static boolean objectStreamClassConstructor(JNIEnvironment jni, Breakpoi
10551055
}
10561056
}
10571057
}
1058-
10591058
for (String className : transitiveSerializeTargets) {
10601059
if (tracer != null) {
10611060
tracer.traceCall("serialization",
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.configure.config;
26+
27+
import com.oracle.svm.configure.json.JsonPrintable;
28+
import com.oracle.svm.configure.json.JsonWriter;
29+
30+
import java.io.IOException;
31+
32+
public abstract class AbstractSerializationConfigurationType implements JsonPrintable {
33+
@Override
34+
public abstract void printJson(JsonWriter writer) throws IOException;
35+
36+
public abstract boolean equals(Object o);
37+
38+
public abstract int hashCode();
39+
}

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/SerializationConfiguration.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
import java.io.IOException;
2929
import java.util.ArrayList;
30-
import java.util.Collections;
3130
import java.util.List;
3231
import java.util.Set;
3332
import java.util.concurrent.ConcurrentHashMap;
@@ -41,7 +40,7 @@
4140

4241
public class SerializationConfiguration implements ConfigurationBase, RuntimeSerializationSupport {
4342

44-
private final Set<SerializationConfigurationType> serializations = ConcurrentHashMap.newKeySet();
43+
private final Set<AbstractSerializationConfigurationType> serializations = ConcurrentHashMap.newKeySet();
4544

4645
public SerializationConfiguration() {
4746
}
@@ -54,21 +53,16 @@ public void removeAll(SerializationConfiguration other) {
5453
serializations.removeAll(other.serializations);
5554
}
5655

57-
public boolean contains(ConfigurationCondition condition, String rawSerializationTargetClass, String customTargetConstructorClass) {
58-
String serializationTargetClass = rawSerializationTargetClass.contains(LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN)
59-
? rawSerializationTargetClass.split(LambdaUtils.SPLIT_BY_LAMBDA)[0] + LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN
60-
: rawSerializationTargetClass;
61-
return serializations.contains(createConfigurationType(condition, serializationTargetClass, customTargetConstructorClass,
62-
serializationTargetClass.contains(LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN)));
56+
public boolean contains(ConfigurationCondition condition, String serializationTargetClass, String customTargetConstructorClass) {
57+
return serializations.contains(createConfigurationType(condition, serializationTargetClass, customTargetConstructorClass));
6358
}
6459

6560
@Override
6661
public void printJson(JsonWriter writer) throws IOException {
6762
writer.append('[').indent();
6863
String prefix = "";
69-
List<SerializationConfigurationType> list = new ArrayList<>(serializations);
70-
Collections.sort(list);
71-
for (SerializationConfigurationType type : list) {
64+
List<AbstractSerializationConfigurationType> list = new ArrayList<>(serializations);
65+
for (AbstractSerializationConfigurationType type : list) {
7266
writer.append(prefix).newline();
7367
type.printJson(writer);
7468
prefix = ",";
@@ -90,20 +84,28 @@ public void registerWithTargetConstructorClass(ConfigurationCondition condition,
9084
}
9185

9286
@Override
93-
public void registerWithTargetConstructorClass(ConfigurationCondition condition, String rawClassName, String customTargetConstructorClassName) {
94-
String className = rawClassName.contains(LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN) ? rawClassName.split(LambdaUtils.SPLIT_BY_LAMBDA)[0] + LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN
95-
: rawClassName;
96-
serializations.add(createConfigurationType(condition, className, customTargetConstructorClassName, rawClassName.contains(LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN)));
87+
public void registerWithTargetConstructorClass(ConfigurationCondition condition, String className, String customTargetConstructorClassName) {
88+
serializations.add(createConfigurationType(condition, className, customTargetConstructorClassName));
89+
}
90+
91+
@Override
92+
public void registerLambdaCapturingClass(ConfigurationCondition condition, String lambdaCapturingClassName) {
93+
serializations.add(createLambdaCapturingClassConfigurationType(condition, lambdaCapturingClassName.split(LambdaUtils.LAMBDA_SPLIT_PATTERN)[0]));
9794
}
9895

9996
@Override
10097
public boolean isEmpty() {
10198
return serializations.isEmpty();
10299
}
103100

104-
private static SerializationConfigurationType createConfigurationType(ConfigurationCondition condition, String className, String customTargetConstructorClassName, boolean isLambdaCapturingClass) {
101+
private static SerializationConfigurationType createConfigurationType(ConfigurationCondition condition, String className, String customTargetConstructorClassName) {
105102
String convertedClassName = SignatureUtil.toInternalClassName(className);
106103
String convertedCustomTargetConstructorClassName = customTargetConstructorClassName == null ? null : SignatureUtil.toInternalClassName(customTargetConstructorClassName);
107-
return new SerializationConfigurationType(condition, convertedClassName, convertedCustomTargetConstructorClassName, isLambdaCapturingClass);
104+
return new SerializationConfigurationType(condition, convertedClassName, convertedCustomTargetConstructorClassName);
105+
}
106+
107+
private static SerializationConfigurationLambdaCapturingType createLambdaCapturingClassConfigurationType(ConfigurationCondition condition, String className) {
108+
String convertedClassName = SignatureUtil.toInternalClassName(className);
109+
return new SerializationConfigurationLambdaCapturingType(condition, convertedClassName);
108110
}
109111
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.configure.config;
26+
27+
import java.io.IOException;
28+
import java.util.Objects;
29+
30+
import org.graalvm.nativeimage.impl.ConfigurationCondition;
31+
32+
import com.oracle.svm.configure.json.JsonWriter;
33+
import com.oracle.svm.core.configure.SerializationConfigurationParser;
34+
35+
public class SerializationConfigurationLambdaCapturingType extends AbstractSerializationConfigurationType implements Comparable<SerializationConfigurationLambdaCapturingType> {
36+
private final ConfigurationCondition condition;
37+
private final String qualifiedJavaName;
38+
39+
public SerializationConfigurationLambdaCapturingType(ConfigurationCondition condition, String qualifiedJavaName) {
40+
assert qualifiedJavaName.indexOf('/') == -1 : "Requires qualified Java name, not internal representation";
41+
assert !qualifiedJavaName.startsWith("[") : "Requires Java source array syntax, for example java.lang.String[]";
42+
Objects.requireNonNull(condition);
43+
this.condition = condition;
44+
Objects.requireNonNull(qualifiedJavaName);
45+
this.qualifiedJavaName = qualifiedJavaName;
46+
}
47+
48+
@Override
49+
public void printJson(JsonWriter writer) throws IOException {
50+
writer.append('{').indent().newline();
51+
ConfigurationConditionPrintable.printConditionAttribute(condition, writer);
52+
53+
writer.quote(SerializationConfigurationParser.LAMBDA_CAPTURING_CLASS_KEY).append(":").quote(qualifiedJavaName);
54+
writer.unindent().newline().append('}');
55+
}
56+
57+
@Override
58+
public boolean equals(Object o) {
59+
if (this == o) {
60+
return true;
61+
}
62+
if (o == null || getClass() != o.getClass()) {
63+
return false;
64+
}
65+
SerializationConfigurationLambdaCapturingType that = (SerializationConfigurationLambdaCapturingType) o;
66+
return condition.equals(that.condition) &&
67+
qualifiedJavaName.equals(that.qualifiedJavaName);
68+
}
69+
70+
@Override
71+
public int hashCode() {
72+
return Objects.hash(condition, qualifiedJavaName);
73+
}
74+
75+
@Override
76+
public int compareTo(SerializationConfigurationLambdaCapturingType other) {
77+
int compareName = qualifiedJavaName.compareTo(other.qualifiedJavaName);
78+
if (compareName != 0) {
79+
return compareName;
80+
}
81+
return condition.compareTo(other.condition);
82+
}
83+
}

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/SerializationConfigurationType.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,17 @@
2828
import java.util.Comparator;
2929
import java.util.Objects;
3030

31-
import org.graalvm.compiler.java.LambdaUtils;
3231
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3332

34-
import com.oracle.svm.configure.json.JsonPrintable;
3533
import com.oracle.svm.configure.json.JsonWriter;
3634
import com.oracle.svm.core.configure.SerializationConfigurationParser;
3735

38-
public class SerializationConfigurationType implements JsonPrintable, Comparable<SerializationConfigurationType> {
36+
public class SerializationConfigurationType extends AbstractSerializationConfigurationType implements Comparable<SerializationConfigurationType> {
3937
private final ConfigurationCondition condition;
4038
private final String qualifiedJavaName;
4139
private final String qualifiedCustomTargetConstructorJavaName;
42-
private final boolean isLambdaCapturingClass;
4340

44-
public SerializationConfigurationType(ConfigurationCondition condition, String qualifiedJavaName, String qualifiedCustomTargetConstructorJavaName, boolean isLambdaCapturingClass) {
41+
public SerializationConfigurationType(ConfigurationCondition condition, String qualifiedJavaName, String qualifiedCustomTargetConstructorJavaName) {
4542
assert qualifiedJavaName.indexOf('/') == -1 : "Requires qualified Java name, not internal representation";
4643
assert !qualifiedJavaName.startsWith("[") : "Requires Java source array syntax, for example java.lang.String[]";
4744
assert qualifiedCustomTargetConstructorJavaName == null || qualifiedCustomTargetConstructorJavaName.indexOf('/') == -1 : "Requires qualified Java name, not internal representation";
@@ -51,21 +48,14 @@ public SerializationConfigurationType(ConfigurationCondition condition, String q
5148
Objects.requireNonNull(qualifiedJavaName);
5249
this.qualifiedJavaName = qualifiedJavaName;
5350
this.qualifiedCustomTargetConstructorJavaName = qualifiedCustomTargetConstructorJavaName;
54-
this.isLambdaCapturingClass = isLambdaCapturingClass;
5551
}
5652

5753
@Override
5854
public void printJson(JsonWriter writer) throws IOException {
5955
writer.append('{').indent().newline();
6056
ConfigurationConditionPrintable.printConditionAttribute(condition, writer);
6157

62-
if (isLambdaCapturingClass) {
63-
String capturingClass = qualifiedJavaName.split(LambdaUtils.SPLIT_BY_LAMBDA)[0];
64-
writer.quote(SerializationConfigurationParser.LAMBDA_CAPTURING_CLASS_KEY).append(":").quote(capturingClass);
65-
} else {
66-
writer.quote(SerializationConfigurationParser.NAME_KEY).append(':').quote(qualifiedJavaName);
67-
}
68-
58+
writer.quote(SerializationConfigurationParser.NAME_KEY).append(':').quote(qualifiedJavaName);
6959
if (qualifiedCustomTargetConstructorJavaName != null) {
7060
writer.append(',').newline();
7161
writer.quote(SerializationConfigurationParser.CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY).append(':')

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/SerializationProcessor.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.List;
2929
import java.util.Map;
3030

31+
import org.graalvm.compiler.java.LambdaUtils;
3132
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3233

3334
import com.oracle.svm.configure.config.SerializationConfiguration;
@@ -54,14 +55,29 @@ void processEntry(Map<String, ?> entry) {
5455
}
5556
String function = (String) entry.get("function");
5657
List<?> args = (List<?>) entry.get("args");
57-
if ("ObjectStreamClass.<init>".equals(function) || "SerializedLambda.readResolve".equals(function)) {
58+
59+
if ("ObjectStreamClass.<init>".equals(function)) {
5860
expectSize(args, 2);
5961

6062
if (advisor.shouldIgnore(LazyValueUtils.lazyValue((String) args.get(0)), LazyValueUtils.lazyValue(null))) {
6163
return;
6264
}
6365

64-
serializationConfiguration.registerWithTargetConstructorClass(condition, (String) args.get(0), (String) args.get(1));
66+
String className = (String) args.get(0);
67+
68+
if (className.contains(LambdaUtils.LAMBDA_CLASS_NAME_PATTERN)) {
69+
serializationConfiguration.registerLambdaCapturingClass(condition, className);
70+
} else {
71+
serializationConfiguration.registerWithTargetConstructorClass(condition, className, (String) args.get(1));
72+
}
73+
} else if ("SerializedLambda.readResolve".equals(function)) {
74+
expectSize(args, 1);
75+
76+
if (advisor.shouldIgnore(LazyValueUtils.lazyValue((String) args.get(0)), LazyValueUtils.lazyValue(null))) {
77+
return;
78+
}
79+
80+
serializationConfiguration.registerLambdaCapturingClass(condition, (String) args.get(0));
6581
}
6682
}
6783
}

0 commit comments

Comments
 (0)