8010010: NPE generating serializedLambdaName for nested lambda
Reviewed-by: mcimadamore
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Mar 14 10:33:31 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Mar 14 22:54:17 2013 -0700
@@ -1293,9 +1293,16 @@
return names.lambda.append(names.fromString("" + lambdaCount++));
}
+ /**
+ * For a serializable lambda, generate a name which maximizes name
+ * stability across deserialization.
+ * @param owner
+ * @return Name to use for the synthetic lambda method name
+ */
private Name serializedLambdaName(Symbol owner) {
StringBuilder buf = new StringBuilder();
buf.append(names.lambda);
+ // Append the name of the method enclosing the lambda.
String methodName = owner.name.toString();
if (methodName.equals("<clinit>"))
methodName = "static";
@@ -1303,9 +1310,18 @@
methodName = "new";
buf.append(methodName);
buf.append('$');
- int methTypeHash = methodSig(owner.type).hashCode();
- buf.append(Integer.toHexString(methTypeHash));
+ // Append a hash of the enclosing method signature to differentiate
+ // overloaded enclosing methods. For lambdas enclosed in lambdas,
+ // the generated lambda method will not have type yet, but the
+ // enclosing method's name will have been generated with this same
+ // method, so it will be unique and never be overloaded.
+ if (owner.type != null) {
+ int methTypeHash = methodSig(owner.type).hashCode();
+ buf.append(Integer.toHexString(methTypeHash));
+ }
buf.append('$');
+ // The above appended name components may not be unique, append a
+ // count based on the above name components.
String temp = buf.toString();
Integer count = serializableLambdaCounts.get(temp);
if (count == null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/LambdaLambdaSerialized.java Thu Mar 14 22:54:17 2013 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+@test
+@bug 8010010
+@summary NPE generating serializedLambdaName for nested lambda
+*/
+
+import java.io.*;
+import java.util.Map;
+import java.util.HashMap;
+
+public class LambdaLambdaSerialized {
+
+ static int assertionCount = 0;
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond)
+ throw new AssertionError();
+ }
+
+ public static void main(String[] args) throws Exception {
+ try {
+ // Write lambdas out
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutput out = new ObjectOutputStream(baos);
+ LSI<LSI<Map>> ssi = () -> (() -> new HashMap());
+ write(out, ssi );
+ out.flush();
+ out.close();
+
+ // Read them back
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ readAssert(in, "[X]");
+ in.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ static void write(ObjectOutput out, LSI<LSI<Map>> lamb) throws IOException {
+ out.writeObject(lamb);
+ }
+
+ static void readAssert(ObjectInputStream in, String expected) throws IOException, ClassNotFoundException {
+ LSI<LSI<Map>> ls = (LSI<LSI<Map>>) in.readObject();
+ Map result = ls.get().get();
+ System.out.printf("Result: %s\n", result);
+ }
+}
+
+interface LSI<T> extends Serializable {
+ T get();
+}