Thu, 26 Mar 2015 11:34:50 +0100
8054220: Debugger doesn't show variables *outside* lambda
8058227: Debugger has no access to outer variables inside Lambda
Summary: Put local variables captured by lambda into the lambda method's LocalVariableTable.
Reviewed-by: mcimadamore, rfield
1 /*
2 * Copyright (c) 2013, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
24 /*
25 * @test
26 * @bug 8023668
27 * @summary Desugar serializable lambda bodies using more robust naming scheme
28 * @library /tools/javac/lib
29 * @build ToolBox
30 * @run main TestSerializedLambdaNameStability
31 */
33 import java.io.*;
34 import java.lang.reflect.Constructor;
35 import java.lang.reflect.InvocationTargetException;
36 import java.lang.reflect.Method;
37 import java.nio.file.*;
39 public class TestSerializedLambdaNameStability {
41 final ClassLoader writingClassLoader;
42 final ClassLoader clonedClassLoader;
43 final ClassLoader checkingClassLoader;
45 TestSerializedLambdaNameStability() {
46 writingClassLoader = new TestClassLoader("before");
47 clonedClassLoader = new TestClassLoader("before");
48 checkingClassLoader = new TestClassLoader("after");
49 }
51 public static void main(String... args) throws Exception {
52 new TestSerializedLambdaNameStability().doit("NameOfCapturedArgs", true);
53 new TestSerializedLambdaNameStability().doit("TypesOfCapturedArgs", true);
54 new TestSerializedLambdaNameStability().doit("OrderOfCapturedArgs", true);
55 new TestSerializedLambdaNameStability().doit("VariableAssignmentTarget", false);
56 new TestSerializedLambdaNameStability().doit("TargetName", true);
57 new TestSerializedLambdaNameStability().doit("TargetType", true);
58 }
60 public void doit(String name, boolean expectFail) throws Exception {
61 String iName = "I" + name;
62 String testName = "TEST" + name;
63 Class<?> kw = writingClassLoader.loadClass(testName);
64 Object instw = getInstance(kw);
65 Method mw = getMethod(kw, "write", ObjectOutput.class);
66 ByteArrayOutputStream baos = new ByteArrayOutputStream();
67 try (ObjectOutput out = new ObjectOutputStream(baos)) {
68 mw.invoke(instw, out);
69 }
70 byte[] ser = baos.toByteArray();
72 // Read and check clone
73 readCheck(iName, testName, clonedClassLoader, ser);
74 System.err.printf("cloned test readCheck %s\n", testName);
76 // Read and check other
77 if (expectFail) {
78 try {
79 readCheck(iName, testName, checkingClassLoader, ser);
80 } catch (InvocationTargetException ite) {
81 Throwable underlying = ite;
82 while (underlying != null && !(underlying instanceof IllegalArgumentException)) {
83 underlying = underlying.getCause();
84 }
85 if (underlying != null) {
86 if (underlying.getMessage().contains("deserialization")) {
87 System.err.printf("PASS: other test %s got expected exception %s\n", testName, underlying);
88 return;
89 }
90 }
91 System.err.printf("FAIL: other test %s got unexpected exception %s\n", testName, ite);
92 throw new Exception("unexpected exception ", ite);
93 }
94 System.err.printf("FAIL: other test %s expected an exception", testName);
95 throw new Exception("expected an exception" + testName);
96 } else {
97 readCheck(iName, testName, checkingClassLoader, ser);
98 System.err.printf("PASS: other test %s readCheck\n", testName);
99 }
100 }
102 void readCheck(String iName, String testName, ClassLoader loader, byte[] ser) throws Exception {
103 Class<?> k = loader.loadClass(testName);
104 Object inst = getInstance(k);
105 Method mrc = getMethod(k, "readCheck", ObjectInput.class);
106 ByteArrayInputStream bais = new ByteArrayInputStream(ser);
107 try (ObjectInput in = new ObjectInputStream(bais)) {
108 mrc.invoke(inst, in);
109 }
110 }
112 Method getMethod(Class<?> k, String name, Class<?> argTypes) throws Exception {
113 Method meth = k.getDeclaredMethod(name, argTypes);
114 meth.setAccessible(true);
115 return meth;
116 }
118 Object getInstance(Class<?> k) throws Exception {
119 Constructor<?> cons = k.getConstructors()[0];
120 cons.setAccessible(true);
121 return cons.newInstance();
122 }
124 static class TestClassLoader extends ClassLoader {
125 static final String compiledDir = System.getProperty("user.dir");
126 static final String sourceBaseDir = System.getProperty("test.src");
128 final String context;
130 public TestClassLoader(String context) {
131 super();
132 this.context = context;
133 }
135 @Override
136 public Class findClass(String name) throws ClassNotFoundException {
137 byte[] b;
139 try {
140 b = loadClassData(name);
141 } catch (Throwable th) {
142 // th.printStackTrace();
143 throw new ClassNotFoundException("Loading error", th);
144 }
145 return defineClass(name, b, 0, b.length);
146 }
148 private byte[] loadClassData(String name) throws Exception {
149 String srcName;
150 if (name.startsWith("TEST"))
151 srcName = name;
152 else if (name.startsWith("I"))
153 srcName = "TEST" + name.substring(1);
154 else
155 throw new Exception("Did not expect to load " + name);
156 Path srcFile = Paths.get(sourceBaseDir, context, srcName + ".java");
157 String testSource = new String(Files.readAllBytes(srcFile));
158 ToolBox.JavaToolArgs javacSuccessArgs =
159 new ToolBox.JavaToolArgs().setSources(testSource);
160 ToolBox.javac(javacSuccessArgs);
161 Path cfFile = Paths.get(compiledDir, name + ".class");
162 byte[] bytes = Files.readAllBytes(cfFile);
163 return bytes;
164 }
165 }
166 }