1 /*******************************************************************************
2  * Copyright (c) 2014, 2017 GoPivotal, Inc. and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *        Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
13  *                          Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
14  *                          Bug 439889 - [1.8][compiler] [lambda] Deserializing lambda fails with IllegalArgumentException: "Invalid lambda deserialization"
15  *                          Bug 442416 - $deserializeLambda$ missing cases for nested lambdas
16  *                          Bug 442418 - $deserializeLambda$ off-by-one error when deserializing the captured arguments of a lambda that also capture this
17  *                          Bug 449467 - [1.8][compiler] Invalid lambda deserialization with anonymous class
18  *        Olivier Tardieu tardieu@us.ibm.com - Contributions for
19  *                          Bug 442416 - $deserializeLambda$ missing cases for nested lambdas
20  *                          Bug 442418 - $deserializeLambda$ off-by-one error when deserializing the captured arguments of a lambda that also capture this
21  *        IBM Corporation - Additional tests
22  *******************************************************************************/
23 package org.eclipse.jdt.core.tests.compiler.regression;
24 
25 import java.io.File;
26 import java.lang.reflect.Modifier;
27 import java.util.Map;
28 
29 import org.eclipse.jdt.core.ToolFactory;
30 import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
31 import org.eclipse.jdt.core.util.IBootstrapMethodsEntry;
32 import org.eclipse.jdt.core.util.IClassFileAttribute;
33 import org.eclipse.jdt.core.util.IClassFileReader;
34 import org.eclipse.jdt.core.util.IConstantPool;
35 import org.eclipse.jdt.core.util.IConstantPoolConstant;
36 import org.eclipse.jdt.core.util.IConstantPoolEntry;
37 import org.eclipse.jdt.core.util.IConstantPoolEntry2;
38 import org.eclipse.jdt.core.util.IMethodInfo;
39 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
40 import org.eclipse.jdt.internal.core.util.BootstrapMethodsAttribute;
41 
42 import junit.framework.Test;
43 
44 @SuppressWarnings({ "unchecked", "rawtypes" })
45 public class SerializableLambdaTest extends AbstractRegressionTest {
46 
47 	static {
48 //		TESTS_NUMBERS = new int [] { 40 };
49 //		TESTS_NAMES = new String[] { "testTypeVariable" };
50 	}
51 
testClass()52 	public static Class testClass() {
53 		return SerializableLambdaTest.class;
54 	}
suite()55 	public static Test suite() {
56 		return buildMinimalComplianceTestSuite(testClass(), F_1_8);
57 	}
SerializableLambdaTest(String testName)58 	public SerializableLambdaTest(String testName){
59 		super(testName);
60 	}
61 
62 	// Enables the tests to run individually
63 	@Override
getCompilerOptions()64 	protected Map getCompilerOptions() {
65 		Map defaultOptions = super.getCompilerOptions();
66 		defaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8);
67 		defaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
68 		defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
69 		return defaultOptions;
70 	}
71 
72 	public static final String RUNNER_CLASS =
73 		"public class Y {\n"+
74 		"  public static void main(String[]args) {\n"+
75 		"    com.foo.X.main(args);\n"+
76 		"  }\n"+
77 		"}";
78 
79 	private static final String HELPER_CLASS =
80 		"package util;\n"+
81 		"import java.io.*;\n"+
82 		"public class Helper {\n"+
83 		"public static void print(Object o ) {System.err.println(o);}\n"+
84 	    "static byte[][] data;\n"+
85 	    "\n"+
86 	    "public static void write(Object o) { write(0,o); }\n"+
87 	    "public static void write(int i, Object o) {\n"+
88 	    "    if (data==null) data=new byte[10][];\n"+
89 	    "    try {\n"+
90 	    "        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n"+
91 	    "        ObjectOutputStream oos = new ObjectOutputStream(baos);\n"+
92 	    "        oos.writeObject(o);\n"+
93 	    "        oos.flush();\n"+
94 	    "        oos.close();\n"+
95 	    "        data[i] = baos.toByteArray();\n"+
96 	    "    } catch (Exception e) {\n"+
97 	    "    }\n"+
98 	    "}\n"+
99 	    "\n"+
100 	    "public static Object read() { return read(0); }\n"+
101 	    "public static Object read(int i) {\n"+
102 	    "    try {\n"+
103 	    "        ByteArrayInputStream bais = new ByteArrayInputStream(data[i]);\n"+
104 	    "        ObjectInputStream ois = new ObjectInputStream(bais);\n"+
105 	    "        Object o = ois.readObject();\n"+
106 	    "        ois.close();\n"+
107 	    "        return o;\n"+
108 	    "    } catch (Exception e) {\n"+
109 	    "    }\n"+
110 	    "    return null;\n"+
111 	    "}\n"+
112 		"}\n";
113 
114 	/**
115 	 * Verifies that after deserializing it is usable, also that the bootstrap methods attribute indicates use of altMetafactory
116 	 */
test001_simple()117 	public void test001_simple() throws Exception {
118 		this.runConformTest(
119 				new String[]{
120 					"X.java",
121 					"import java.io.*;\n"+
122 					"public class X {\n"+
123 					"    interface Foo extends Serializable { int m(); }\n"+
124 					"\n"+
125 					"    public static void main(String[] args) {\n"+
126 					"        Foo f1 = null;\n"+
127 					"        f1 = () -> 3;\n"+
128 					"        util.Helper.write(f1);\n"+
129 					"        f1 = (Foo)util.Helper.read();\n"+
130 					"        System.out.println(f1.m());\n"+
131 					"    }\n"+
132 					"}\n",
133 					"Helper.java",HELPER_CLASS,
134 					},
135 					"3",
136 					null,
137 					true,
138 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
139 		String expectedOutput =
140 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
141 				"  Method arguments:\n"+
142 				"    ()I\n"+
143 				"    invokestatic X.lambda$0:()I\n"+
144 				"    ()I\n"+
145 				"    1\n";
146 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
147 		checkExpected(expectedOutput,data);
148 	}
149 
150 	/**
151 	 * Sanity test, non serializable should have bootstrap methods attribute reference to metafactory.
152 	 */
test002_simpleNonSerializable()153 	public void test002_simpleNonSerializable() throws Exception {
154 		this.runConformTest(
155 				new String[]{
156 					"X.java",
157 					"import java.io.*;\n"+
158 					"public class X {\n"+
159 					"    interface Foo { int m(); }\n"+
160 					"\n"+
161 					"    public static void main(String[] args) {\n"+
162 					"        Foo f1 = null;\n"+
163 					"        f1 = () -> 3;\n"+
164 					"        System.out.println(f1.m());\n"+
165 					"    }\n"+
166 					"}\n",
167 					"Helper.java",HELPER_CLASS,
168 					},
169 					"3");
170 		String expectedOutput =
171 				"0: invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\n"+
172 				"  Method arguments:\n"+
173 				"    ()I\n"+
174 				"    invokestatic X.lambda$0:()I\n"+
175 				"    ()I\n";
176 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
177 		checkExpected(expectedOutput,data);
178 	}
179 
180 	/**
181 	 * Basic test that deserializeLambda can cope with two lambda expressions.
182 	 */
test003_twoSerializedLambdas()183 	public void test003_twoSerializedLambdas() throws Exception {
184 		this.runConformTest(
185 				new String[]{
186 					"X.java",
187 					"import java.io.*;\n"+
188 					"public class X {\n"+
189 					"    interface Foo extends Serializable { int m(); }\n"+
190 					"\n"+
191 					"    public static void main(String[] args) {\n"+
192 					"        Foo f1 = null, f2 = null;\n"+
193 					"        f1 = () -> 33;\n"+
194 					"        f2 = () -> 99;\n"+
195 					"        util.Helper.write(0,f1);\n"+
196 					"        util.Helper.write(1,f2);\n"+
197 					"        f2 = (Foo)util.Helper.read(1);\n"+
198 					"        f1 = (Foo)util.Helper.read(0);\n"+
199 					"        System.out.println(f1.m());\n"+
200 					"        System.out.println(f2.m());\n"+
201 					"    }\n"+
202 					"}\n",
203 					"Helper.java",HELPER_CLASS,
204 					},
205 					"33\n99",
206 					null,
207 					true,
208 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
209 		String expectedOutput =
210 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
211 				"  Method arguments:\n"+
212 				"    ()I\n"+
213 				"    invokestatic X.lambda$0:()I\n"+
214 				"    ()I\n"+
215 				"    1\n"+
216 				"1: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
217 				"  Method arguments:\n"+
218 				"    ()I\n"+
219 				"    invokestatic X.lambda$1:()I\n"+
220 				"    ()I\n"+
221 				"    1\n";
222 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
223 		checkExpected(expectedOutput,data);
224 	}
225 
test004_lambdaWithParameterInPackage()226 	public void test004_lambdaWithParameterInPackage() throws Exception {
227 		this.runConformTest(
228 				new String[]{
229 					"Y.java",
230 					"public class Y {\n"+
231 					"  public static void main(String[]args) {\n"+
232 					"    com.foo.X.main(args);\n"+
233 					"  }\n"+
234 					"}",
235 					"X.java",
236 					"package com.foo;\n"+
237 					"import java.io.*;\n"+
238 					"public class X {\n"+
239 					"    interface Foo extends Serializable { int m(int i); }\n"+
240 					"\n"+
241 					"    public static void main(String[] args) {\n"+
242 					"        Foo f1 = null, f2 = null;\n"+
243 					"        f1 = (i) -> i*2;\n"+
244 					"        util.Helper.write(f1);\n"+
245 					"        f1 = (Foo)util.Helper.read();\n"+
246 					"        System.out.println(f1.m(4));\n"+
247 					"    }\n"+
248 					"}\n",
249 					"Helper.java",HELPER_CLASS,
250 					},
251 					"8",
252 					null,
253 					true,
254 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
255 		String expectedOutput =
256 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
257 				"  Method arguments:\n"+
258 				"    (I)I\n"+
259 				"    invokestatic com/foo/X.lambda$0:(I)I\n"+
260 				"    (I)I\n"+
261 				"    1\n";
262 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
263 		checkExpected(expectedOutput,data);
264 	}
265 
test005_capturingVariableLambdaWithParameterInPackage()266 	public void test005_capturingVariableLambdaWithParameterInPackage() throws Exception {
267 		this.runConformTest(
268 				new String[]{
269 					"Y.java",
270 					"public class Y {\n"+
271 					"  public static void main(String[]args) {\n"+
272 					"    com.foo.X.main(args);\n"+
273 					"  }\n"+
274 					"}",
275 					"X.java",
276 					"package com.foo;\n"+
277 					"import java.io.*;\n"+
278 					"public class X {\n"+
279 					"    interface Foo extends Serializable { int m(int i); }\n"+
280 					"\n"+
281 					"    public static void main(String[] args) {\n"+
282 					"        Foo f1 = null;\n"+
283 					"        int multiplier = 3;\n"+
284 					"        f1 = (i) -> i * multiplier;\n"+
285 					"        util.Helper.write(f1);\n"+
286 					"        f1 = (Foo)util.Helper.read();\n"+
287 					"        System.out.println(f1.m(4));\n"+
288 					"    }\n"+
289 					"}\n",
290 					"Helper.java",HELPER_CLASS,
291 					},
292 					"12",
293 					null,
294 					true,
295 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
296 		String expectedOutput =
297 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
298 				"  Method arguments:\n"+
299 				"    (I)I\n"+
300 				"    invokestatic com/foo/X.lambda$0:(II)I\n"+
301 				"    (I)I\n"+
302 				"    1\n";
303 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
304 		checkExpected(expectedOutput,data);
305 	}
306 
307 	// differing types, not just int
test006_capturingVariableLambdaWithParameterInPackage()308 	public void test006_capturingVariableLambdaWithParameterInPackage() throws Exception {
309 		this.runConformTest(
310 				new String[]{
311 					"Y.java",
312 					"public class Y {\n"+
313 					"  public static void main(String[]args) {\n"+
314 					"    com.foo.X.main(args);\n"+
315 					"  }\n"+
316 					"}",
317 					"X.java",
318 					"package com.foo;\n"+
319 					"import java.io.*;\n"+
320 					"public class X {\n"+
321 					"    interface Foo extends Serializable { int m(String n); }\n"+
322 					"\n"+
323 					"    public static void main(String[] args) {\n"+
324 					"        Foo f1 = null;\n"+
325 					"        int multiplier = 3;\n"+
326 					"        f1 = (n) -> Integer.valueOf(n) * multiplier;\n"+
327 					"        util.Helper.write(f1);\n"+
328 					"        f1 = (Foo)util.Helper.read();\n"+
329 					"        System.out.println(f1.m(\"33\"));\n"+
330 					"    }\n"+
331 					"}\n",
332 					"Helper.java",HELPER_CLASS,
333 					},
334 					"99",
335 					null,
336 					true,
337 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
338 		String expectedOutput =
339 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
340 				"  Method arguments:\n"+
341 				"    (Ljava/lang/String;)I\n"+
342 				"    invokestatic com/foo/X.lambda$0:(ILjava/lang/String;)I\n"+
343 				"    (Ljava/lang/String;)I\n"+
344 				"    1\n";
345 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
346 		checkExpected(expectedOutput,data);
347 	}
348 
349 	// Fails the same way as javac right now... with NPE (b120)
xtest007_capturingFieldLambdaWithParameterInPackage()350 	public void xtest007_capturingFieldLambdaWithParameterInPackage() throws Exception {
351 		this.runConformTest(
352 				new String[]{
353 					"Y.java",
354 					"public class Y {\n"+
355 					"  public static void main(String[]args) {\n"+
356 					"    com.foo.X.main(args);\n"+
357 					"  }\n"+
358 					"}",
359 					"X.java",
360 					"package com.foo;\n"+
361 					"import java.io.*;\n"+
362 					"public class X {\n"+
363 					"    int multiplier = 3;\n"+
364 					"    interface Foo extends Serializable { int m(int i); }\n"+
365 					"\n"+
366 					"    public static void main(String[] args) {\n"+
367 					"      new X().run();\n"+
368 					"    }\n"+
369 					"    public void run() {\n"+
370 					"        Foo f1 = null;\n"+
371 					"        f1 = (i) -> i * this.multiplier;\n"+
372 					"        util.Helper.write(f1);\n"+
373 					"        f1 = (Foo)util.Helper.read();\n"+
374 					"        System.out.println(f1.m(4));\n"+
375 					"    }\n"+
376 					"}\n",
377 					"Helper.java",HELPER_CLASS,
378 					},
379 					"12",
380 					null,
381 					true,
382 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
383 		String expectedOutput =
384 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
385 				"  Method arguments:\n"+
386 				"    (I)I\n"+
387 				"    invokestatic com/foo/X.lambda$0:(II)I\n"+
388 				"    (I)I\n"+
389 				"    1\n";
390 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
391 		checkExpected(expectedOutput,data);
392 	}
393 
test008_capturingTwoVariableLambdaWithParameterInPackage()394 	public void test008_capturingTwoVariableLambdaWithParameterInPackage() throws Exception {
395 		this.runConformTest(
396 				new String[]{
397 					"Y.java",
398 					"public class Y {\n"+
399 					"  public static void main(String[]args) {\n"+
400 					"    com.foo.X.main(args);\n"+
401 					"  }\n"+
402 					"}",
403 					"X.java",
404 					"package com.foo;\n"+
405 					"import java.io.*;\n"+
406 					"public class X {\n"+
407 					"    interface Foo extends Serializable { float m(int i, float f); }\n"+
408 					"\n"+
409 					"    public static void main(String[] args) {\n"+
410 					"      new X().run();\n"+
411 					"    }\n"+
412 					"    public void run() {\n"+
413 					"        Foo f1 = null;\n"+
414 					"        f1 = (i,f) -> ((float)i) * f;\n"+
415 					"        util.Helper.write(f1);\n"+
416 					"        f1 = (Foo)util.Helper.read();\n"+
417 					"        System.out.println(f1.m(3,4.0f));\n"+
418 					"    }\n"+
419 					"}\n",
420 					"Helper.java",HELPER_CLASS,
421 					},
422 					"12.0",
423 					null,
424 					true,
425 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
426 		String expectedOutput =
427 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
428 				"  Method arguments:\n"+
429 				"    (IF)F\n"+
430 				"    invokestatic com/foo/X.lambda$0:(IF)F\n"+
431 				"    (IF)F\n"+
432 				"    1\n";
433 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
434 		checkExpected(expectedOutput,data);
435 	}
436 
test009_capturingTwoSlotVariablesLambdaWithParameterInPackage()437 	public void test009_capturingTwoSlotVariablesLambdaWithParameterInPackage() throws Exception {
438 		this.runConformTest(
439 				new String[]{
440 					"Y.java",RUNNER_CLASS,
441 					"X.java",
442 					"package com.foo;\n"+
443 					"import java.io.*;\n"+
444 					"public class X {\n"+
445 					"    interface Foo extends Serializable { double m(int i, long l); }\n"+
446 					"\n"+
447 					"    public static void main(String[] args) {\n"+
448 					"      new X().run();\n"+
449 					"    }\n"+
450 					"    public void run() {\n"+
451 					"        Foo f1 = null;\n"+
452 					"        f1 = (i,l) -> (double)(i*l);\n"+
453 					"        util.Helper.write(f1);\n"+
454 					"        f1 = (Foo)util.Helper.read();\n"+
455 					"        System.out.println(f1.m(3,40L));\n"+
456 					"    }\n"+
457 					"}\n",
458 					"Helper.java",HELPER_CLASS,
459 					},
460 					"120.0",
461 					null,
462 					true,
463 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
464 		String expectedOutput =
465 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
466 				"  Method arguments:\n"+
467 				"    (IJ)D\n"+
468 				"    invokestatic com/foo/X.lambda$0:(IJ)D\n"+
469 				"    (IJ)D\n"+
470 				"    1\n";
471 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
472 		checkExpected(expectedOutput,data);
473 	}
474 
test010_VarargsLambdaExpression()475 	public void test010_VarargsLambdaExpression() throws Exception {
476 		this.runConformTest(
477 				new String[]{
478 					"Y.java",RUNNER_CLASS,
479 					"X.java",
480 					"package com.foo;\n"+
481 					"import java.io.*;\n"+
482 					"public class X {\n"+
483 					"    interface Foo extends Serializable { String m(String... ss); }\n"+
484 					"\n"+
485 					"    public static void main(String[] args) {\n"+
486 					"      new X().run();\n"+
487 					"    }\n"+
488 					"    public void run() {\n"+
489 					"        Foo f1 = null;\n"+
490 					"        f1 = (strings) -> strings[0]+strings[1];\n"+
491 					"        util.Helper.write(f1);\n"+
492 					"        f1 = (Foo)util.Helper.read();\n"+
493 					"        System.out.println(f1.m(\"abc\",\"def\"));\n"+
494 					"    }\n"+
495 					"}\n",
496 					"Helper.java",HELPER_CLASS,
497 					},
498 					"abcdef",
499 					null,
500 					true,
501 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
502 		String expectedOutput =
503 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
504 				"  Method arguments:\n"+
505 				"    ([Ljava/lang/String;)Ljava/lang/String;\n"+
506 				"    invokestatic com/foo/X.lambda$0:([Ljava/lang/String;)Ljava/lang/String;\n"+
507 				"    ([Ljava/lang/String;)Ljava/lang/String;\n"+
508 				"    1\n";
509 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
510 		checkExpected(expectedOutput,data);
511 	}
512 
513 	// Fails same way as javac right now... with an NPE (b120)
xtest011_CapturingInstance()514 	public void xtest011_CapturingInstance() throws Exception {
515 		this.runConformTest(
516 				new String[]{
517 					"Y.java",RUNNER_CLASS,
518 					"X.java",
519 					"package com.foo;\n"+
520 					"import java.io.*;\n"+
521 					"public class X {\n"+
522 					"    interface Foo extends Serializable { String m(); }\n"+
523 					"\n"+
524 					"    String fieldValue = \"hello\";\n"+
525 					"    public static void main(String[] args) {\n"+
526 					"      new X().run();\n"+
527 					"    }\n"+
528 					"    public void run() {\n"+
529 					"        Foo f1 = null;\n"+
530 					"        f1 = () -> this.fieldValue;\n"+
531 					"        util.Helper.write(f1);\n"+
532 					"        f1 = (Foo)util.Helper.read();\n"+
533 					"        System.out.println(f1.m());\n"+
534 					"    }\n"+
535 					"}\n",
536 					"Helper.java",HELPER_CLASS,
537 					},
538 					"abcdef",
539 					null,
540 					true,
541 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
542 		String expectedOutput =
543 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
544 				"  Method arguments:\n"+
545 				"    ([Ljava/lang/String;)Ljava/lang/String;\n"+
546 				"    invokestatic com/foo/X.lambda$0:([Ljava/lang/String;)Ljava/lang/String;\n"+
547 				"    ([Ljava/lang/String;)Ljava/lang/String;\n"+
548 				"    1\n";
549 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "com"+File.separator+"foo"+File.separator+"X.class");
550 		checkExpected(expectedOutput,data);
551 	}
552 
test012_intersectionCast()553 	public void test012_intersectionCast() throws Exception {
554 		this.runConformTest(
555 				new String[]{
556 					"X.java",
557 					"import java.io.*;\n"+
558 					"public class X {\n"+
559 					"    interface Foo extends Serializable { int m(); }\n"+
560 					"    interface Marker {}\n"+
561 					"\n"+
562 					"    public static void main(String[] args) {\n"+
563 					"        Foo f1 = null;\n"+
564 					"        f1 = (Foo & Marker) () -> 3;\n"+
565 					"        System.out.println(\"isMarker?\"+(f1 instanceof Marker));\n"+
566 					"        util.Helper.write(f1);\n"+
567 					"        f1 = (Foo)util.Helper.read();\n"+
568 					"        System.out.println(f1.m());\n"+
569 					"        System.out.println(\"isMarker?\"+(f1 instanceof Marker));\n"+
570 					"    }\n"+
571 					"}\n",
572 					"Helper.java",HELPER_CLASS,
573 					},
574 					"isMarker?true\n3\nisMarker?true",
575 					null,
576 					true,
577 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
578 		String expectedOutput =
579 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
580 				"  Method arguments:\n"+
581 				"    ()I\n"+
582 				"    invokestatic X.lambda$0:()I\n"+
583 				"    ()I\n"+
584 				"    3\n"+ // BitFlags: 0x01 = FLAG_SERIALIZABLE 0x02 = FLAG_MARKER
585 				"    1\n"+ // Marker interface count
586 				"    X$Marker\n";
587 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
588 		checkExpected(expectedOutput,data);
589 	}
590 
test013_intersectionCast()591 	public void test013_intersectionCast() throws Exception {
592 		this.runConformTest(
593 				new String[]{
594 					"X.java",
595 					"import java.io.*;\n"+
596 					"interface Goo {}\n"+
597 					"public class X {\n"+
598 					"    interface Foo extends Serializable { int m(); }\n"+
599 					"    interface Marker {}\n"+
600 					"\n"+
601 					"    public static void main(String[] args) {\n"+
602 					"        Foo f1 = null;\n"+
603 					"        f1 = (Foo & Goo & Serializable & Marker) () -> 3;\n"+
604 					"        System.out.println(\"isMarker?\"+(f1 instanceof Marker));\n"+
605 					"        System.out.println(\"isGoo?\"+(f1 instanceof Goo));\n"+
606 					"        System.out.println(\"isSerializable?\"+(f1 instanceof Serializable));\n"+
607 					"        util.Helper.write(f1);\n"+
608 					"        f1 = (Foo)util.Helper.read();\n"+
609 					"        System.out.println(f1.m());\n"+
610 					"        System.out.println(\"isMarker?\"+(f1 instanceof Marker));\n"+
611 					"        System.out.println(\"isGoo?\"+(f1 instanceof Goo));\n"+
612 					"        System.out.println(\"isSerializable?\"+(f1 instanceof Serializable));\n"+
613 					"    }\n"+
614 					"}\n",
615 					"Helper.java",HELPER_CLASS,
616 					},
617 					"isMarker?true\nisGoo?true\nisSerializable?true\n3\nisMarker?true\nisGoo?true\nisSerializable?true",
618 					null,
619 					true,
620 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
621 		String expectedOutput =
622 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
623 				"  Method arguments:\n"+
624 				"    ()I\n"+
625 				"    invokestatic X.lambda$0:()I\n"+
626 				"    ()I\n"+
627 				"    3\n"+ // BitFlags: 0x01 = FLAG_SERIALIZABLE 0x02 = FLAG_MARKER
628 				"    2\n"+ // Marker interface count
629 				"    Goo\n"+
630 				"    X$Marker\n";
631 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
632 		checkExpected(expectedOutput,data);
633 	}
634 
test014_intersectionCastAndNotSerializable()635 	public void test014_intersectionCastAndNotSerializable() throws Exception {
636 		this.runConformTest(
637 				new String[]{
638 					"X.java",
639 					"import java.io.*;\n"+
640 					"interface Goo {}\n"+
641 					"public class X {\n"+
642 					"    interface Foo { int m(); }\n"+
643 					"    interface Marker {}\n"+
644 					"\n"+
645 					"    public static void main(String[] args) {\n"+
646 					"        Foo f1 = null;\n"+
647 					"        f1 = (Foo & Goo & Marker) () -> 3;\n"+
648 					"        System.out.println(\"isMarker?\"+(f1 instanceof Marker));\n"+
649 					"        System.out.println(\"isGoo?\"+(f1 instanceof Goo));\n"+
650 					"        System.out.println(\"isSerializable?\"+(f1 instanceof Serializable));\n"+
651 					"        System.out.println(f1.m());\n"+
652 					"    }\n"+
653 					"}\n",
654 					"Helper.java",HELPER_CLASS,
655 					},
656 					"isMarker?true\nisGoo?true\nisSerializable?false\n3",
657 					null,
658 					true,
659 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
660 		String expectedOutput =
661 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
662 				"  Method arguments:\n"+
663 				"    ()I\n"+
664 				"    invokestatic X.lambda$0:()I\n"+
665 				"    ()I\n"+
666 				"    2\n"+ // BitFlags: 0x02 = FLAG_MARKER
667 				"    2\n"+ // Marker interface count
668 				"    Goo\n"+
669 				"    X$Marker\n";
670 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
671 		checkExpected(expectedOutput,data);
672 	}
673 
test015_serializableViaIntersectionCast()674 	public void test015_serializableViaIntersectionCast() throws Exception {
675 		this.runConformTest(
676 				new String[]{
677 					"X.java",
678 					"import java.io.*;\n"+
679 					"interface Goo {}\n"+
680 					"public class X {\n"+
681 					"    interface Foo { int m(); }\n"+
682 					"    interface Marker {}\n"+
683 					"\n"+
684 					"    public static void main(String[] args) {\n"+
685 					"        Foo f1 = null;\n"+
686 					"        f1 = (Foo & Goo & Serializable & Marker) () -> 3;\n"+
687 					"        System.out.println(\"isMarker?\"+(f1 instanceof Marker));\n"+
688 					"        System.out.println(\"isGoo?\"+(f1 instanceof Goo));\n"+
689 					"        System.out.println(\"isSerializable?\"+(f1 instanceof Serializable));\n"+
690 					"        util.Helper.write(f1);\n"+
691 					"        f1 = (Foo)util.Helper.read();\n"+
692 					"        System.out.println(f1.m());\n"+
693 					"        System.out.println(\"isMarker?\"+(f1 instanceof Marker));\n"+
694 					"        System.out.println(\"isGoo?\"+(f1 instanceof Goo));\n"+
695 					"        System.out.println(\"isSerializable?\"+(f1 instanceof Serializable));\n"+
696 					"    }\n"+
697 					"}\n",
698 					"Helper.java",HELPER_CLASS,
699 					},
700 					"isMarker?true\nisGoo?true\nisSerializable?true\n3\nisMarker?true\nisGoo?true\nisSerializable?true",
701 					null,
702 					true,
703 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
704 		String expectedOutput =
705 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
706 				"  Method arguments:\n"+
707 				"    ()I\n"+
708 				"    invokestatic X.lambda$0:()I\n"+
709 				"    ()I\n"+
710 				"    3\n"+ // BitFlags: 0x01 = FLAG_SERIALIZABLE 0x02 = FLAG_MARKER
711 				"    2\n"+ // Marker interface count
712 				"    Goo\n"+
713 				"    X$Marker\n";
714 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
715 		checkExpected(expectedOutput,data);
716 	}
717 
718 	// SAM type not first in intersection cast
test016_bug424211()719 	public void test016_bug424211() throws Exception {
720 		this.runConformTest(
721 				new String[]{
722 					"X.java",
723 					"import java.io.Serializable;\n"+
724 					"public class X {\n"+
725 					"	public static void main(String argv[]) throws Exception {\n"+
726 					"		AutoCloseable one = ((Serializable & AutoCloseable) (() -> {}));\n"+
727 					"		one.close();\n"+
728 					"	}\n"+
729 					"}"
730 					},
731 					"",
732 					null,
733 					true,
734 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
735 		String expectedOutput =
736 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
737 				"  Method arguments:\n"+
738 				"    ()V\n"+
739 				"    invokestatic X.lambda$0:()V\n"+
740 				"    ()V\n"+
741 				"    1\n";
742 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
743 		checkExpected(expectedOutput,data);
744 	}
745 
746 	// Now SAM type first
test017_bug424211()747 	public void test017_bug424211() throws Exception {
748 		this.runConformTest(
749 				new String[]{
750 					"X.java",
751 					"import java.io.Serializable;\n"+
752 					"public class X {\n"+
753 					"	public static void main(String argv[]) throws Exception {\n"+
754 					"		AutoCloseable one = ((AutoCloseable & Serializable) (() -> {}));\n"+
755 					"		one.close();\n"+
756 					"	}\n"+
757 					"}"
758 					},
759 					"",
760 					null,
761 					true,
762 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
763 		String expectedOutput =
764 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
765 				"  Method arguments:\n"+
766 				"    ()V\n"+
767 				"    invokestatic X.lambda$0:()V\n"+
768 				"    ()V\n"+
769 				"    1\n";
770 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
771 		checkExpected(expectedOutput,data);
772 	}
773 
774 	// Not Serializable but a regular marker interface
test018_bug424211()775 	public void test018_bug424211() throws Exception {
776 		this.runConformTest(
777 				new String[]{
778 					"X.java",
779 					"import java.io.Serializable;\n"+
780 					"interface Marker {}\n"+
781 					"public class X {\n"+
782 					"	public static void main(String argv[]) throws Exception {\n"+
783 					"		AutoCloseable one = ((Marker & AutoCloseable) (() -> {}));\n"+
784 					"		one.close();\n"+
785 					"	}\n"+
786 					"}"
787 					},
788 					"",
789 					null,
790 					true,
791 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
792 		String expectedOutput =
793 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
794 				"  Method arguments:\n"+
795 				"    ()V\n"+
796 				"    invokestatic X.lambda$0:()V\n"+
797 				"    ()V\n"+
798 				"    2\n"+
799 				"    1\n"+
800 				"    Marker\n";
801 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
802 		checkExpected(expectedOutput,data);
803 	}
804 
805 	// Now SAM type not first and serialization occurring
test019_bug424211()806 	public void test019_bug424211() throws Exception {
807 		this.runConformTest(
808 				new String[]{
809 					"X.java",
810 					"import java.io.Serializable;\n"+
811 					"interface SAM {int m();}\n"+
812 					"public class X {\n"+
813 					"	public static void main(String argv[]) throws Exception {\n"+
814 					"		SAM one = ((Serializable & SAM) (() -> 3));\n"+
815 					"        System.out.println(one.m());\n"+
816 					"        util.Helper.write(one);\n"+
817 					"        one = (SAM)util.Helper.read();\n"+
818 					"        System.out.println(one.m());\n"+
819 					"	}\n"+
820 					"}",
821 					"Helper.java",HELPER_CLASS,
822 					},
823 					"3\n3",
824 					null,
825 					true,
826 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
827 		String expectedOutput =
828 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
829 				"  Method arguments:\n"+
830 				"    ()I\n"+
831 				"    invokestatic X.lambda$0:()I\n"+
832 				"    ()I\n"+
833 				"    1\n";
834 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
835 		checkExpected(expectedOutput,data);
836 	}
837 
test020_lambdaNames()838 	public void test020_lambdaNames() throws Exception {
839 		this.runConformTest(
840 				new String[]{
841 					"X.java",
842 					"import java.io.Serializable;\n"+
843 					"interface Foo {int m();}\n"+
844 					"interface FooN extends Serializable {int m();}\n"+
845 					"public class X {\n"+
846 					"	public static void main(String argv[]) throws Exception {\n"+
847 					"		AutoCloseable one = () -> {};\n"+
848 					"       new X().m();\n"+
849 					"       one.close();\n"+
850 					"	}\n"+
851 					"   public void m() { Foo f = () -> 3; System.out.println(f.m());}\n"+
852 					"   public void n() { FooN f = () -> 3; System.out.println(f.m());}\n"+
853 					"}"
854 					},
855 					"3",
856 					null,
857 					true,
858 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
859 		String expectedOutput =
860 			"  private static synthetic void lambda$0() throws java.lang.Exception;\n";
861 		checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
862 		expectedOutput =
863 			"  private static synthetic int lambda$1();\n";
864 		checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
865 	}
866 
test021_lambdaNamesVariants()867 	public void test021_lambdaNamesVariants() throws Exception {
868 		this.runConformTest(
869 				new String[]{
870 					"X.java",
871 					"import java.io.Serializable;\n"+
872 					"interface Foo {int m();}\n"+
873 					"interface FooSer extends Serializable {int m();}\n"+
874 					"interface FooI {int m(int i);}\n"+
875 					"interface FooSerI extends Serializable {int m(int i);}\n"+
876 					"public class X {\n"+
877 					"\n"+
878 					"   Foo instanceField = () -> 1;\n"+
879 					"   FooSer instanceFieldSer = () -> 2;\n"+
880 					"   static Foo staticField = () -> 3;\n"+
881 					"   static FooSer staticFieldSer = () -> 4;\n"+
882 					"   FooI instanceFieldI = (i) -> 5;\n"+
883 					"   FooSerI instanceFieldSerI = (i) -> 6;\n"+
884 					"\n"+
885 					"	public static void main(String argv[]) throws Exception {\n"+
886 					"     int x = 4;\n"+
887 					"     Foo a = () -> 1;\n"+
888 					"     FooSer b = () -> 2;\n"+
889 					"     FooI c = (i) -> 3;\n"+
890 					"     FooSerI d = (i) -> 4;\n"+
891 					"     Foo e = () -> x;\n"+
892 					"     FooSer f = () -> x+1;\n"+
893 					"     FooI g = (i) -> x+2;\n"+
894 					"     FooSerI h = (i) -> x+3;\n"+
895 					"	}\n"+
896 					"}"
897 					},
898 					"",
899 					null,
900 					true,
901 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
902 		String expectedOutput =
903 				"static lambda$2()I\n"+
904 				"static lambda$3()I\n"+
905 				"static lambda$0()I\n"+
906 				"static lambda$1()I\n"+
907 				"static lambda$4(I)I\n"+
908 				"static lambda$5(I)I\n"+
909 				"static lambda$6()I\n"+
910 				"static lambda$7()I\n"+
911 				"static lambda$8(I)I\n"+
912 				"static lambda$9(I)I\n"+
913 				"static lambda$10(I)I\n"+
914 				"static lambda$11(I)I\n"+
915 				"static lambda$12(II)I\n"+
916 				"static lambda$13(II)I\n";
917 		String actualOutput = printLambdaMethods(OUTPUT_DIR + File.separator + "X.class");
918 		if (!actualOutput.equals(expectedOutput)) {
919 			printIt(actualOutput);
920 			assertEquals(expectedOutput,actualOutput);
921 		}
922 	}
923 
test022_nestedLambdas()924 	public void test022_nestedLambdas() throws Exception {
925 		this.runConformTest(
926 				new String[]{
927 					"X.java",
928 					"import java.io.Serializable;\n"+
929 					"interface Foo extends Serializable {int m();}\n"+
930 					"public class X {\n"+
931 					"	public static void main(String argv[]) throws Exception {\n"+
932 					"		Foo f = () -> { return ((Foo)()->33).m();};\n"+
933 					"       System.out.println(f.m());\n"+
934 					"       util.Helper.write(f);\n"+
935 					"       f = (Foo)util.Helper.read();\n"+
936 					"       System.out.println(f.m());\n"+
937 					"	}\n"+
938 					"}",
939 					"Helper.java",HELPER_CLASS,
940 					},
941 					"33\n33",
942 					null,
943 					true,
944 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
945 		String expectedOutput =
946 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
947 				"  Method arguments:\n"+
948 				"    ()I\n"+
949 				"    invokestatic X.lambda$0:()I\n"+
950 				"    ()I\n"+
951 				"    1\n"+
952 				"1: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
953 				"  Method arguments:\n"+
954 				"    ()I\n"+
955 				"    invokestatic X.lambda$1:()I\n"+
956 				"    ()I\n"+
957 				"    1\n";
958 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
959 		checkExpected(expectedOutput,data);
960 	}
961 
test023_lambdasInOtherPlaces_Field()962 	public void test023_lambdasInOtherPlaces_Field() throws Exception {
963 		this.runConformTest(
964 				new String[]{
965 					"X.java",
966 					"import java.io.Serializable;\n"+
967 					"interface Foo extends Serializable {int m();}\n"+
968 					"public class X {\n"+
969 					"   Foo f = () -> 99;\n" +
970 					"	public static void main(String argv[]) throws Exception {\n"+
971 					"     new X().run();\n"+
972 					"   }\n"+
973 					"   public void run() {\n"+
974 					"       System.out.println(f.m());\n"+
975 					"       util.Helper.write(f);\n"+
976 					"       f = (Foo)util.Helper.read();\n"+
977 					"       System.out.println(f.m());\n"+
978 					"	}\n"+
979 					"}",
980 					"Helper.java",HELPER_CLASS,
981 					},
982 					"99\n99",
983 					null,
984 					true,
985 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
986 		String expectedOutput =
987 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
988 				"  Method arguments:\n"+
989 				"    ()I\n"+
990 				"    invokestatic X.lambda$0:()I\n"+
991 				"    ()I\n"+
992 				"    1\n";
993 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
994 		checkExpected(expectedOutput,data);
995 	}
996 
test024_lambdasInOtherPlaces_MethodParameter()997 	public void test024_lambdasInOtherPlaces_MethodParameter() throws Exception {
998 		this.runConformTest(
999 				new String[]{
1000 					"X.java",
1001 					"import java.io.Serializable;\n"+
1002 					"interface Foo extends Serializable {int m();}\n"+
1003 					"public class X {\n"+
1004 					"	public static void main(String argv[]) throws Exception {\n"+
1005 					"       new X().run(()->33);\n"+
1006 					"   }\n"+
1007 					"   public void run(Foo f) {\n"+
1008 					"       System.out.println(f.m());\n"+
1009 					"       util.Helper.write(f);\n"+
1010 					"       f = (Foo)util.Helper.read();\n"+
1011 					"       System.out.println(f.m());\n"+
1012 					"	}\n"+
1013 					"}",
1014 					"Helper.java",HELPER_CLASS,
1015 					},
1016 					"33\n33",
1017 					null,
1018 					true,
1019 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1020 		String expectedOutput =
1021 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
1022 				"  Method arguments:\n"+
1023 				"    ()I\n"+
1024 				"    invokestatic X.lambda$0:()I\n"+
1025 				"    ()I\n"+
1026 				"    1\n";
1027 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
1028 		checkExpected(expectedOutput,data);
1029 	}
1030 
test025_lambdasWithGenericInferencing()1031 	public void test025_lambdasWithGenericInferencing() throws Exception {
1032 		this.runConformTest(
1033 				new String[]{
1034 					"X.java",
1035 					"import java.io.Serializable;\n"+
1036 					"import java.util.function.*;\n"+
1037 					"public class X {\n"+
1038 					"	public static void main(String argv[]) throws Exception {\n"+
1039 					"       new X().run();\n"+
1040 					"   }\n"+
1041 					"   public void run() {\n"+
1042 					"       IntFunction<Integer> times3 = (IntFunction<Integer> & Serializable) (triple) -> 3 * triple;\n"+
1043 					"       System.out.println(times3.apply(4));\n"+
1044 					"       util.Helper.write(times3);\n"+
1045 					"       times3 = (IntFunction<Integer>)util.Helper.read();\n"+
1046 					"       System.out.println(times3.apply(4));\n"+
1047 					"	}\n"+
1048 					"}",
1049 					"Helper.java",HELPER_CLASS,
1050 					},
1051 					"12\n12",
1052 					null,
1053 					true,
1054 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1055 		String expectedOutput =
1056 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
1057 				"  Method arguments:\n"+
1058 				"    (I)Ljava/lang/Object;\n"+
1059 				"    invokestatic X.lambda$0:(I)Ljava/lang/Integer;\n"+
1060 				"    (I)Ljava/lang/Integer;\n"+
1061 				"    1\n";
1062 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
1063 		checkExpected(expectedOutput,data);
1064 	}
test026_lambdasInOtherPlaces_Clinit()1065 	public void test026_lambdasInOtherPlaces_Clinit() throws Exception {
1066 		this.runConformTest(
1067 				new String[]{
1068 					"X.java",
1069 					"import java.io.Serializable;\n"+
1070 					"interface Foo extends Serializable {int m();}\n"+
1071 					"public class X {\n"+
1072 					"   static {\n"+
1073 					"     Foo f = () -> 99;\n" +
1074 					"   }\n"+
1075 					"	public static void main(String argv[]) throws Exception {\n"+
1076 					"     new X().run();\n"+
1077 					"   }\n"+
1078 					"   public void run() {\n"+
1079 					"       Foo f = ()->99;\n"+
1080 					"       System.out.println(f.m());\n"+
1081 					"       util.Helper.write(f);\n"+
1082 					"       f = (Foo)util.Helper.read();\n"+
1083 					"       System.out.println(f.m());\n"+
1084 					"	}\n"+
1085 					"}",
1086 					"Helper.java",HELPER_CLASS,
1087 					},
1088 					"99\n99",
1089 					null,
1090 					true,
1091 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1092 		String expectedOutput =
1093 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
1094 				"  Method arguments:\n"+
1095 				"    ()I\n"+
1096 				"    invokestatic X.lambda$0:()I\n"+
1097 				"    ()I\n"+
1098 				"    1\n"+
1099 				"1: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
1100 				"  Method arguments:\n"+
1101 				"    ()I\n"+
1102 				"    invokestatic X.lambda$1:()I\n"+
1103 				"    ()I\n"+
1104 				"    1\n";
1105 		String data = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "X.class");
1106 		checkExpected(expectedOutput,data);
1107 	}
1108 
1109 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=449467 - [1.8][compiler] Invalid lambda deserialization with anonymous class
test449467()1110 	public void test449467() throws Exception {
1111 		this.runConformTest(
1112 				new String[]{
1113 					"TestClass.java",
1114 					"import java.io.ByteArrayInputStream;\n"+
1115 					"import java.io.ByteArrayOutputStream;\n"+
1116 					"import java.io.ObjectInputStream;\n"+
1117 					"import java.io.ObjectOutputStream;\n"+
1118 					"import java.io.Serializable;\n"+
1119 					"\n"+
1120 					"public class TestClass implements Serializable {\n"+
1121 					"  String msg = \"HEY!\";\n"+
1122 					"  OtherClass other;\n"+
1123 					"\n"+
1124 					"  public TestClass(StringBuilder sb) {\n"+
1125 					"    other = new OtherClass() {\n"+
1126 					"      {\n"+
1127 					"        other2 = new OtherClass2((Runnable & Serializable) () -> {\n"+
1128 					"          sb.length();\n"+
1129 					"          say();\n"+
1130 					"        });\n"+
1131 					"      }\n"+
1132 					"    };\n"+
1133 					"  }\n"+
1134 					"\n"+
1135 					"  public void say() {\n"+
1136 					"    System.out.println(msg);\n"+
1137 					"  }\n"+
1138 					"\n"+
1139 					"  public static void main(String[] args) throws Exception {\n"+
1140 					"    ByteArrayOutputStream buffer = new ByteArrayOutputStream();\n"+
1141 					"    try (ObjectOutputStream out = new ObjectOutputStream(buffer)) {\n"+
1142 					"      out.writeObject(new TestClass(new StringBuilder()));\n"+
1143 					"    }\n"+
1144 					"    try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) {\n"+
1145 					"      TestClass s = (TestClass) in.readObject();\n"+
1146 					"      s.say();\n"+
1147 					"    }\n"+
1148 					"  }\n"+
1149 					"}\n"+
1150 					"\n"+
1151 					"class OtherClass implements Serializable {\n"+
1152 					"  OtherClass2 other2;\n"+
1153 					"}\n"+
1154 					"\n"+
1155 					"class OtherClass2 implements Serializable {\n"+
1156 					"  Runnable runnable;\n"+
1157 					"\n"+
1158 					"  public OtherClass2(Runnable runnable) {\n"+
1159 					"    this.runnable = runnable;\n"+
1160 					"  }\n"+
1161 					"}\n"
1162 					},
1163 					"HEY!",
1164 					null,
1165 					true,
1166 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1167 	}
1168 
test449467_2()1169 	public void test449467_2() throws Exception {
1170 		this.runConformTest(
1171 				new String[]{
1172 					"com/foo/TestClass.java",
1173 					"package com.foo;\n"+
1174 					"import java.io.ByteArrayInputStream;\n"+
1175 					"import java.io.ByteArrayOutputStream;\n"+
1176 					"import java.io.ObjectInputStream;\n"+
1177 					"import java.io.ObjectOutputStream;\n"+
1178 					"import java.io.Serializable;\n"+
1179 					"public class TestClass implements Serializable {\n"+
1180 					"  String msg = \"HEY!\";\n"+
1181 					"  OtherClass other;\n"+
1182 					"\n"+
1183 					"  public TestClass(StringBuilder sb) {\n"+
1184 					"    other = new OtherClass() {\n"+
1185 					"      {\n"+
1186 					"        other2 = new OtherClass2((Runnable & Serializable) () -> {\n"+
1187 					"          sb.length();\n"+
1188 					"          say();\n"+
1189 					"        });\n"+
1190 					"      }\n"+
1191 					"    };\n"+
1192 					"  }\n"+
1193 					"\n"+
1194 					"  public void say() {\n"+
1195 					"    System.out.println(msg);\n"+
1196 					"  }\n"+
1197 					"\n"+
1198 					"  public static void main(String[] args) throws Exception {\n"+
1199 					"    ByteArrayOutputStream buffer = new ByteArrayOutputStream();\n"+
1200 					"    try (ObjectOutputStream out = new ObjectOutputStream(buffer)) {\n"+
1201 					"      out.writeObject(new TestClass(new StringBuilder()));\n"+
1202 					"    }\n"+
1203 					"    try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) {\n"+
1204 					"      TestClass s = (TestClass) in.readObject();\n"+
1205 					"      s.say();\n"+
1206 					"    }\n"+
1207 					"  }\n"+
1208 					"}\n"+
1209 					"\n"+
1210 					"class OtherClass implements Serializable {\n"+
1211 					"  OtherClass2 other2;\n"+
1212 					"}\n"+
1213 					"\n"+
1214 					"class OtherClass2 implements Serializable {\n"+
1215 					"  Runnable runnable;\n"+
1216 					"\n"+
1217 					"  public OtherClass2(Runnable runnable) {\n"+
1218 					"    this.runnable = runnable;\n"+
1219 					"  }\n"+
1220 					"}\n"
1221 					},
1222 					"HEY!",
1223 					null,
1224 					true,
1225 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1226 	}
1227 
1228 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=428552,  [1.8][compiler][codegen] Serialization does not work for method references
test428552()1229 	public void test428552() throws Exception {
1230 		this.runConformTest(
1231 				new String[]{
1232 					"X.java",
1233 					"import java.io.*;\n" +
1234 					"public class X {\n" +
1235 					"	interface Example extends Serializable {\n" +
1236 					"		String convert(X o);\n" +
1237 					"	}\n" +
1238 					"	public static void main(String[] args) throws IOException {\n" +
1239 					"		Example e=X::toString;\n" +
1240 					"       util.Helper.write(e);\n"+
1241 					"       e = (Example)util.Helper.read();\n"+
1242 					"       System.out.println(e.convert(new X()));\n"+
1243 					"	}\n" +
1244 					"   public String toString() {\n" +
1245 					"       return \"XItIs\";\n" +
1246 					"   }\n" +
1247 					"}\n",
1248 					"Helper.java",HELPER_CLASS,
1249 					},
1250 					"XItIs",
1251 					null,
1252 					true,
1253 					new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1254 	}
1255 
1256 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=428642
test428642()1257 	public void test428642() throws Exception {
1258 		this.runConformTest(
1259 				new String[]{
1260 					"QuickSerializedLambdaTest.java",
1261 					"import java.io.*;\n"+
1262 					"import java.util.function.IntConsumer;\n"+
1263 					"\n"+
1264 					"public class QuickSerializedLambdaTest {\n"+
1265 					"	interface X extends IntConsumer,Serializable{}\n"+
1266 					"	public static void main(String[] args) throws IOException, ClassNotFoundException {\n"+
1267 					"		X x2 = System::exit; // method reference\n"+
1268 					"		ByteArrayOutputStream debug=new ByteArrayOutputStream();\n"+
1269 					"		try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n"+
1270 					"		{\n"+
1271 					"			oo.writeObject(x2);\n"+
1272 					"		}\n"+
1273 					"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n"+
1274 					"		{\n"+
1275 					"			X x=(X)oi.readObject();\n"+
1276 					"			x.accept(0);// shall exit\n"+
1277 					"		}\n"+
1278 					"		throw new AssertionError(\"should not reach this point\");\n"+
1279 					"	}\n"+
1280 					"}\n",
1281 					"Helper.java",
1282 					"public class Helper {\n"+
1283 					"  public static String tostring(java.lang.invoke.SerializedLambda sl) {\n"+
1284 					"    return sl.toString();\n"+
1285 					"  }\n"+
1286 					"}"
1287 				},
1288 				"",
1289 				null,true,
1290 				new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1291 	}
1292 
test428642_2()1293 	public void test428642_2() throws Exception {
1294 		this.runConformTest(
1295 				new String[]{
1296 					"Helper.java",
1297 					"public class Helper {\n"+
1298 					"  public static String tostring(java.lang.invoke.SerializedLambda sl) {\n"+
1299 					"    return sl.toString();\n"+
1300 					"  }\n"+
1301 					"  public static void main(String[]argv) throws Exception {\n"+
1302 					"    foo.QuickSerializedLambdaTest.main(argv);\n"+
1303 					"  }\n"+
1304 					"}",
1305 					"QuickSerializedLambdaTest.java",
1306 					"package foo;\n"+
1307 					"import java.io.*;\n"+
1308 					"import java.util.function.IntConsumer;\n"+
1309 					"\n"+
1310 					"public class QuickSerializedLambdaTest {\n"+
1311 					"	interface X extends IntConsumer,Serializable{}\n"+
1312 					"	public static void main(String[] args) throws IOException, ClassNotFoundException {\n"+
1313 					"		X x1 = i -> System.out.println(i);// lambda expression\n"+
1314 					"		X x2 = System::exit; // method reference\n"+
1315 					"		ByteArrayOutputStream debug=new ByteArrayOutputStream();\n"+
1316 					"		try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n"+
1317 					"		{\n"+
1318 					"			oo.writeObject(x1);\n"+
1319 					"			oo.writeObject(x2);\n"+
1320 					"		}\n"+
1321 					"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n"+
1322 					"		{\n"+
1323 					"			X x=(X)oi.readObject();\n"+
1324 					"			x.accept(42);// shall print \"42\"\n"+
1325 					"			x=(X)oi.readObject();\n"+
1326 					"			x.accept(0);// shall exit\n"+
1327 					"		}\n"+
1328 					"		throw new AssertionError(\"should not reach this point\");\n"+
1329 					"	}\n"+
1330 					"}\n"
1331 				},
1332 				"42",
1333 				null,true,
1334 				new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1335 	}
1336 
1337 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=429112, [1.8][compiler] Exception when compiling Serializable array constructor reference
test429112()1338 	public void test429112() throws Exception {
1339 		this.runConformTest(
1340 				new String[]{
1341 					"X.java",
1342 					"import java.io.*;\n" +
1343 					"import java.util.function.IntFunction;\n" +
1344 					"public class X {\n" +
1345 					"  interface IF extends IntFunction<Object>, Serializable {}\n" +
1346 					"  public static void main(String[] args) throws IOException, ClassNotFoundException {\n" +
1347 					"    IF factory=String[]::new;\n" +
1348 					"    Object o = factory.apply(1234);\n" +
1349 					"		ByteArrayOutputStream debug=new ByteArrayOutputStream();\n"+
1350 					"		try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n"+
1351 					"		{\n"+
1352 					"			oo.writeObject(factory);\n"+
1353 					"		}\n"+
1354 					"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n"+
1355 					"		{\n"+
1356 					"			IF x = (IF)oi.readObject();\n"+
1357 					"			Object p = x.apply(1234);\n"+
1358 					"           System.out.println(p.getClass());\n" +
1359 					"           String [] sa = (String []) p;\n" +
1360 					"           System.out.println(sa.length);\n" +
1361 					"		}\n"+
1362 					"	}\n"+
1363 					"}\n",
1364 				},
1365 				"class [Ljava.lang.String;\n" +
1366 				"1234",
1367 				null,true,
1368 				new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1369 	}
1370 
1371 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=439889 - [1.8][compiler] [lambda] Deserializing lambda fails with IllegalArgumentException: "Invalid lambda deserialization"
test439889()1372 	public void test439889() throws Exception {
1373 		this.runConformTest(
1374 				new String[]{
1375 					"SerializationTest.java",
1376 					"import java.io.*;\n"+
1377 					"\n"+
1378 					"public class SerializationTest implements Serializable {\n"+
1379 					"	interface SerializableRunnable extends Runnable, Serializable {\n"+
1380 					"	}\n"+
1381 					"\n"+
1382 					"	SerializableRunnable runnable;\n"+
1383 					"\n"+
1384 					"	public SerializationTest() {\n"+
1385 					"		final SerializationTest self = this;\n"+
1386 					"		// runnable = () -> self.doSomething();\n"+
1387 					"		runnable = () -> this.doSomething();\n"+ // results in this method handle: #166 invokespecial SerializationTest.lambda$0:()V
1388 					"       }\n"+
1389 					"\n"+
1390 					"	public void doSomething() {\n"+
1391 					"		System.out.println(\"Hello,world!\");\n"+
1392 					"	}\n"+
1393 					"\n"+
1394 					"	public static void main(String[] args) throws Exception {\n"+
1395 					"		final ByteArrayOutputStream buffer = new ByteArrayOutputStream();\n"+
1396 					"		try (ObjectOutputStream out = new ObjectOutputStream(buffer) ) {\n"+
1397 					"			out.writeObject(new SerializationTest());\n"+
1398 					"		}\n"+
1399 					"		try (ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(buffer.toByteArray()))) {\n"+
1400 					"			final SerializationTest s = (SerializationTest) in.readObject();\n"+
1401 					"			s.doSomething();\n"+
1402 					"		}\n"+
1403 					"	}\n"+
1404 					"}\n"
1405 					},
1406 					"Hello,world!",
1407 					null,true,
1408 					new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1409 	}
1410 
test439889_2()1411 	public void test439889_2() throws Exception {
1412 		this.runConformTest(
1413 				new String[]{
1414 					"SerializationTest.java",
1415 					"import java.io.*;\n"+
1416 					"\n"+
1417 					"public class SerializationTest implements Serializable {\n"+
1418 					"	interface SerializableRunnable extends Runnable, Serializable {\n"+
1419 					"	}\n"+
1420 					"\n"+
1421 					"	SerializableRunnable runnable;\n"+
1422 					"\n"+
1423 					"	public SerializationTest() {\n"+
1424 					"		final SerializationTest self = this;\n"+
1425 					"		runnable = () -> self.doSomething();\n"+ // results in this method handle: #168 invokestatic SerializationTest.lambda$0:(LSerializationTest;)V
1426 					"		// runnable = () -> this.doSomething();\n"+
1427 					"       }\n"+
1428 					"\n"+
1429 					"	public void doSomething() {\n"+
1430 					"		System.out.println(\"Hello,world!\");\n"+
1431 					"	}\n"+
1432 					"\n"+
1433 					"	public static void main(String[] args) throws Exception {\n"+
1434 					"		final ByteArrayOutputStream buffer = new ByteArrayOutputStream();\n"+
1435 					"		try (ObjectOutputStream out = new ObjectOutputStream(buffer) ) {\n"+
1436 					"			out.writeObject(new SerializationTest());\n"+
1437 					"		}\n"+
1438 					"		try (ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(buffer.toByteArray()))) {\n"+
1439 					"			final SerializationTest s = (SerializationTest) in.readObject();\n"+
1440 					"			s.doSomething();\n"+
1441 					"		}\n"+
1442 					"	}\n"+
1443 					"}\n"
1444 					},
1445 					"Hello,world!",
1446 					null,true,
1447 					new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1448 	}
1449 
testNestedLambdas_442416()1450 	public void testNestedLambdas_442416() throws Exception {
1451 		this.runConformTest(
1452 				new String[]{
1453 					"Foo.java",
1454 					"import java.io.*;\n"+
1455 					"public class Foo {\n"+
1456 					"   static byte[] toSer(Object o) {\n"+
1457 					"       try {\n"+
1458 					"			final ByteArrayOutputStream buffer = new ByteArrayOutputStream();\n"+
1459 					"			try (ObjectOutputStream out = new ObjectOutputStream(buffer) ) {\n"+
1460 					"				out.writeObject(o);\n"+
1461 					"			}\n"+
1462 					"			return buffer.toByteArray();\n"+
1463 					"       } catch (Exception e) {e.printStackTrace();return null;}\n"+
1464 					"   }\n"+
1465 					"   static Object fromSer(byte[] bs) {\n"+
1466 					"       try {\n"+
1467 					"			try (ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(bs))) {\n"+
1468 					"				final Object s = in.readObject();\n"+
1469 					"				return s;\n"+
1470 					"			}\n"+
1471 					"       } catch (Exception e) {e.printStackTrace();return null;}\n"+
1472 					"   }\n"+
1473 					"	public static void main(String[] args) throws Exception {\n"+
1474 					"       Runnable nested1,nested2;\n"+
1475 					"		Runnable lambda0 = (java.io.Serializable & Runnable) () -> {\n"+
1476 					"			Runnable lambda1 = (java.io.Serializable & Runnable) () -> {\n"+
1477 					"				Runnable lambda2 = (java.io.Serializable & Runnable) () -> {\n"+
1478 					"					System.out.println(\"Hello,world!\");\n"+
1479 					"				};\n"+
1480 					"       		byte[] bs = toSer(lambda2);\n"+
1481 					"				Runnable r = (Runnable)fromSer(bs);\n"+
1482 					"       		r.run();\n"+
1483 					"			};\n"+
1484 					"       	byte[] bs = toSer(lambda1);\n"+
1485 					"			Runnable r = (Runnable)fromSer(bs);\n"+
1486 					"       	r.run();\n"+
1487 					"		};\n"+
1488 					"       byte[] bs = toSer(lambda0);\n"+
1489 					"		Runnable r = (Runnable)fromSer(bs);\n"+
1490 					"       r.run();\n"+
1491 					"	}\n"+
1492 					"}\n",
1493 				},
1494 				"Hello,world!",
1495 				null,true,
1496 				new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1497 	}
1498 
testBindingThis_442418()1499 	public void testBindingThis_442418() throws Exception {
1500 		this.runConformTest(
1501 				new String[]{
1502 					"Foo.java",
1503 					"import java.io.*;\n"+
1504 					"public class Foo implements Serializable {\n"+
1505 					"   static byte[] toSer(Object o) {\n"+
1506 					"       try {\n"+
1507 					"			final ByteArrayOutputStream buffer = new ByteArrayOutputStream();\n"+
1508 					"			try (ObjectOutputStream out = new ObjectOutputStream(buffer) ) {\n"+
1509 					"				out.writeObject(o);\n"+
1510 					"			}\n"+
1511 					"			return buffer.toByteArray();\n"+
1512 					"		} catch (Exception e) {e.printStackTrace();return null;}\n"+
1513 					"	}\n"+
1514 					"	static Object fromSer(byte[] bs) {\n"+
1515 					"	try {\n"+
1516 					"			try (ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(bs))) {\n"+
1517 					"				final Object s = in.readObject();\n"+
1518 					"				return s;\n"+
1519 					"			}\n"+
1520 					"       } catch (Exception e) {e.printStackTrace();return null;}\n"+
1521 					"   }\n"+
1522 					"		void m(int i) {\n"+
1523 					"			System.out.println(i);\n"+
1524 					"		}\n"+
1525 					"		void n(int i) {\n"+
1526 					"			Runnable lambda = (java.io.Serializable & Runnable) () -> { this.m(i); };\n"+
1527 					"			byte[] bs = toSer(lambda);\n"+
1528 					"			Runnable r = (Runnable)fromSer(bs);\n"+
1529 					"			r.run();\n"+
1530 					"		}\n"+
1531 					"	public static void main(String[] args) throws Exception {\n"+
1532 					"		new Foo().n(42);\n"+
1533 					"	}\n"+
1534 					"}\n",
1535 				},
1536 				"42",
1537 				null,true,
1538 				new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
1539 	}
1540 
testbug479119()1541 	public void testbug479119() {
1542 		this.runConformTest(
1543 			new String[]{
1544 				"Testbed.java",
1545 				"import java.io.ObjectStreamClass;\n" +
1546 				"import java.io.Serializable;\n" +
1547 				"import java.lang.invoke.SerializedLambda;\n" +
1548 				"import java.lang.reflect.Method;\n" +
1549 				"import java.util.function.IntFunction;\n" +
1550 				"import java.util.stream.Stream;\n" +
1551 				"public class Testbed {\n" +
1552 				"	public static void main(String[] args) {\n" +
1553 				"		System.out.println(getMethod(Testbed::foo).equals(getMethod(Testbed::foo)));\n" +
1554 				"	}\n" +
1555 				"	private static void foo() { }\n" +
1556 				"	static interface MethodRef extends Runnable, Serializable { }\n" +
1557 				"	private static Method getMethod(MethodRef methodRef) {\n" +
1558 				"		try {\n" +
1559 				"			final Method invokeWriteReplaceMethod = ObjectStreamClass.class.getDeclaredMethod(\"invokeWriteReplace\", Object.class);\n" +
1560 				"			invokeWriteReplaceMethod.setAccessible(true);\n" +
1561 				"			final SerializedLambda l = (SerializedLambda)invokeWriteReplaceMethod.invoke(\n" +
1562 				"					ObjectStreamClass.lookupAny(methodRef.getClass()),\n" +
1563 				"					methodRef\n" +
1564 				"				);\n" +
1565 				"			System.out.println(\"Looking for \" + l.getImplClass() + \".\" + l.getImplMethodName());\n" +
1566 				"			final Method[] methods = Stream.of(Class.forName(l.getImplClass()).getDeclaredMethods()).\n" +
1567 				"				filter(m -> m.getName().equals(l.getImplMethodName())).\n" +
1568 				"				toArray(Method[]::new);\n" +
1569 				"			if(methods.length != 1) throw new AssertionError(\"TODO: check signature\");\n" +
1570 				"			return methods[0];\n" +
1571 				"		} catch(Exception e) {\n" +
1572 				"			throw new RuntimeException(e);\n" +
1573 				"		}\n" +
1574 				"	}\n" +
1575 				"}\n"
1576 		},
1577 		"Looking for Testbed.foo\n" +
1578 		"Looking for Testbed.foo\n" +
1579 		"true",
1580 		null,true,
1581 		(isJRE9Plus
1582 		? new String[] { "--add-opens", "java.base/java.io=ALL-UNNAMED" }
1583 		: new String [] { "-Ddummy" })
1584 		);
1585 
1586 
1587 		String bootstrapEntries = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "Testbed.class");
1588 		String expectedOutput =
1589 				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
1590 				"  Method arguments:\n"+
1591 				"    ()V\n"+
1592 				"    invokestatic Testbed.foo:()V\n"+
1593 				"    ()V\n"+
1594 				"    1\n"+
1595 				"1: invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\n"+
1596 				"  Method arguments:\n"+
1597 				"    (Ljava/lang/Object;)Z\n"+
1598 				"    invokestatic Testbed.lambda$2:(Ljava/lang/invoke/SerializedLambda;Ljava/lang/reflect/Method;)Z\n"+
1599 				"    (Ljava/lang/reflect/Method;)Z\n"+
1600 				"2: invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\n"+
1601 				"  Method arguments:\n"+
1602 				"    (I)Ljava/lang/Object;\n"+
1603 				"    invokestatic Testbed.lambda$3:(I)[Ljava/lang/reflect/Method;\n"+
1604 				"    (I)[Ljava/lang/reflect/Method;\n";
1605 
1606 		checkExpected(expectedOutput, bootstrapEntries);
1607 	}
1608 
testbug479119a()1609 	public void testbug479119a() {
1610 		this.runConformTest(
1611 			new String[]{
1612 				"Testbed.java",
1613 				"import java.io.ObjectStreamClass;\n" +
1614 				"import java.io.Serializable;\n" +
1615 				"import java.lang.invoke.SerializedLambda;\n" +
1616 				"import java.lang.reflect.Constructor;\n" +
1617 				"import java.lang.reflect.Executable;\n" +
1618 				"import java.lang.reflect.Method;\n" +
1619 				"import java.util.function.IntFunction;\n" +
1620 				"import java.util.stream.Stream;\n" +
1621 				"public class Testbed {\n" +
1622 				"	public static void main(String[] args) {\n" +
1623 				"		System.out.println(getMethod(Testbed::foo).equals(getMethod(Testbed::foo)));\n" +
1624 				"		System.out.println(getMethod(new Foo()::method).equals(getMethod(new Bar()::method)));\n" +
1625 				"		System.out.println(getMethod(MethodRefImpl::new).equals(getMethod(MethodRefImpl::new)));\n" +
1626 				"	}\n" +
1627 				"	static class MethodRefImpl implements MethodRef {\n" +
1628 				"		@Override\n" +
1629 				"		public void run() {}\n" +
1630 				"	}\n" +
1631 				"	public static class Base {\n" +
1632 				"        public void method () {}\n" +
1633 				"    }\n" +
1634 				"    public static class Foo extends Base {}\n" +
1635 				"    public static class Bar extends Base {}\n" +
1636 				"	private static void foo() { }\n" +
1637 				"	static interface MethodRef extends Runnable, Serializable { }\n" +
1638 				"	private static Executable getMethod(MethodRef methodRef) {\n" +
1639 				"		try {\n" +
1640 				"			final Method invokeWriteReplaceMethod = ObjectStreamClass.class.getDeclaredMethod(\"invokeWriteReplace\", Object.class);\n" +
1641 				"			invokeWriteReplaceMethod.setAccessible(true);\n" +
1642 				"			final SerializedLambda l = (SerializedLambda)invokeWriteReplaceMethod.invoke(\n" +
1643 				"					ObjectStreamClass.lookupAny(methodRef.getClass()),\n" +
1644 				"					methodRef\n" +
1645 				"				);\n" +
1646 				"			System.out.println(\"Looking for \" + l.getImplClass() + \".\" + l.getImplMethodName());\n" +
1647 				"			boolean isConstructor = l.getImplMethodName().indexOf(\"<init>\") >= 0;\n" +
1648 				"			final Executable[] methods = Stream.of(isConstructor ? Class.forName(l.getImplClass()).getDeclaredConstructors() : Class.forName(l.getImplClass()).getDeclaredMethods()).\n" +
1649 				"				filter(m -> m.getName().equals(isConstructor ? l.getImplClass() : l.getImplMethodName())).\n" +
1650 				"				toArray(isConstructor ? Constructor[]::new : Method[]::new);\n" +
1651 				"			if(methods.length != 1) throw new AssertionError(\"TODO: check signature\");\n" +
1652 				"			return methods[0];\n" +
1653 				"		} catch(Exception e) {\n" +
1654 				"			throw new RuntimeException(e);\n" +
1655 				"		}\n" +
1656 				"	}\n" +
1657 				"}\n"
1658 		},
1659 		"Looking for Testbed.foo\n" +
1660 		"Looking for Testbed.foo\n" +
1661 		"true\n" +
1662 		"Looking for Testbed$Base.method\n" +
1663 		"Looking for Testbed$Base.method\n" +
1664 		"true\n" +
1665 		"Looking for Testbed$MethodRefImpl.<init>\n" +
1666 		"Looking for Testbed$MethodRefImpl.<init>\n" +
1667 		"true",
1668 		null,true,
1669 		(isJRE9Plus
1670 		? new String[] { "--add-opens", "java.base/java.io=ALL-UNNAMED" }
1671 		: new String [] { "-Ddummy" })
1672 		);
1673 	}
1674 
1675 	// Serializable reference expressions that share the same name
testbug479119b()1676 	public void testbug479119b() {
1677 		this.runConformTest(
1678 			new String[]{
1679 				"X.java",
1680 				"import java.io.ByteArrayInputStream;\n" +
1681 				"import java.io.ByteArrayOutputStream;\n" +
1682 				"import java.io.IOException;\n" +
1683 				"import java.io.ObjectInputStream;\n" +
1684 				"import java.io.ObjectOutputStream;\n" +
1685 				"import java.io.Serializable;\n" +
1686 				"public class X {\n" +
1687 				"    public static interface Consumer<T> extends Serializable {\n" +
1688 				"        void accept(T t);\n" +
1689 				"    }\n" +
1690 				"    public static class Foo {\n" +
1691 				"    	public void method () {\n" +
1692 				"        	System.out.println(\"Foo\");\n" +
1693 				"        }\n" +
1694 				"    }\n" +
1695 				"    public static class Bar {\n" +
1696 				"    	public void method () {\n" +
1697 				"        	System.out.println(\"Bar\");\n" +
1698 				"        }\n" +
1699 				"    }\n" +
1700 				"    public static void main (String[] args) throws IOException, ClassNotFoundException {\n" +
1701 				"        Consumer<Foo> foo = Foo::method;\n" +
1702 				"        Consumer<Bar> bar = Bar::method;\n" +
1703 				"        Consumer<Foo> baz = (b) -> {b.method();};\n" +
1704 				"        ByteArrayOutputStream debug=new ByteArrayOutputStream();\n" +
1705 				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug)) {\n" +
1706 				"			oo.writeObject(bar);\n" +
1707 				"		}\n" +
1708 				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray()))) {\n" +
1709 				"			Consumer<Bar> x = (Consumer)oi.readObject();\n" +
1710 				"			x.accept(new Bar());\n" +
1711 				"		}\n" +
1712 				"		debug.reset();\n" +
1713 				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug)) {\n" +
1714 				"			oo.writeObject(foo);\n" +
1715 				"		}\n" +
1716 				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray()))) {\n" +
1717 				"			Consumer<Foo> x = (Consumer)oi.readObject();\n" +
1718 				"			x.accept(new Foo());\n" +
1719 				"		}\n" +
1720 				"    }\n" +
1721 				"}\n"
1722 		},
1723 		"Bar\n" +
1724 		"Foo",
1725 		null,true,
1726 		new String[]{"-Ddummy"});
1727 	}
testbug479119_comment20()1728 	public void testbug479119_comment20() {
1729 		this.runConformTest(
1730 			new String[]{
1731 				"Testbed.java",
1732 				"import java.io.ByteArrayInputStream;\n" +
1733 				"import java.io.ByteArrayOutputStream;\n" +
1734 				"import java.io.IOException;\n" +
1735 				"import java.io.ObjectInputStream;\n" +
1736 				"import java.io.ObjectOutputStream;\n" +
1737 				"import java.io.Serializable;\n" +
1738 				"interface FI extends Serializable{\n" +
1739 				"	void run(Testbed args);\n" +
1740 				"}\n" +
1741 				"interface IF extends Serializable{\n" +
1742 				"	void run();\n" +
1743 				"}\n" +
1744 				"public class Testbed implements Serializable{\n" +
1745 				"	String f;\n" +
1746 				"	Testbed(String str) {\n" +
1747 				"		f = str;\n" +
1748 				"	}\n" +
1749 				"	void test() throws IOException, ClassNotFoundException {\n" +
1750 				"		accept(Testbed::foo);\n" +
1751 				"		accept(this::foo);		\n" +
1752 				"	}\n" +
1753 				"	void foo() {\n" +
1754 				"		System.out.println(this.f);\n" +
1755 				"	}\n" +
1756 				"	void accept(FI fi) {\n" +
1757 				"		fi.run(this);\n" +
1758 				"	}\n" +
1759 				"	void accept(IF i) {\n" +
1760 				"		i.run();\n" +
1761 				"	}\n" +
1762 				"	public static void main(String[] args) throws ClassNotFoundException, IOException {\n" +
1763 				"		Testbed t = new Testbed(\"IF\");\n" +
1764 				"		Testbed t2 = new Testbed(\"FI\");\n" +
1765 				"		IF i = t::foo;\n" +
1766 				"		FI f = Testbed::foo;\n" +
1767 				"		ByteArrayOutputStream debug=new ByteArrayOutputStream();\n" +
1768 				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n" +
1769 				"		{\n" +
1770 				"			oo.writeObject(i);\n" +
1771 				"		}\n" +
1772 				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n" +
1773 				"		{\n" +
1774 				"			IF x = (IF)oi.readObject();\n" +
1775 				"			t.accept(x);\n" +
1776 				"		}\n" +
1777 				"		debug=new ByteArrayOutputStream();\n" +
1778 				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n" +
1779 				"		{\n" +
1780 				"			oo.writeObject(f);\n" +
1781 				"		}\n" +
1782 				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n" +
1783 				"		{\n" +
1784 				"			FI x = (FI)oi.readObject();\n" +
1785 				"			t2.accept(x);\n" +
1786 				"		}\n" +
1787 				"	}\n" +
1788 				"}"
1789 		},
1790 		"IF\n" +
1791 		"FI",
1792 		null,true,
1793 		new String[]{"-Ddummy"});
1794 	}
testbug485333()1795 	public void testbug485333() {
1796 		this.runConformTest(
1797 			new String[]{
1798 				"Test.java",
1799 				"import java.io.ByteArrayInputStream;\n" +
1800 				"import java.io.ByteArrayOutputStream;\n" +
1801 				"import java.io.ObjectInputStream;\n" +
1802 				"import java.io.ObjectOutputStream;\n" +
1803 				"import java.io.Serializable;\n" +
1804 				"interface Func<T> extends Serializable {\n" +
1805 				"  T get();\n" +
1806 				"}\n" +
1807 				"class Impl implements Serializable {\n" +
1808 				"  int val = 0;\n" +
1809 				"  public int next() {\n" +
1810 				"    val += 1;\n" +
1811 				"    return val;\n" +
1812 				"  }\n" +
1813 				"}\n" +
1814 				"public class Test {\n" +
1815 				"  final Impl impl = new Impl();\n" +
1816 				"  final Func<Integer> func = (Func<Integer> & Cloneable)impl::next;\n" +
1817 				"  public void test() throws Throwable {\n" +
1818 				"    byte[] bytes = write(func);//25\n" +
1819 				"    Func<Integer> func = read(bytes);\n" +
1820 				"    System.out.println(func.get());\n" +
1821 				"  }\n" +
1822 				"  public static void main(String[] args) throws Throwable {\n" +
1823 				"	new Test().test();\n" +
1824 				"}\n" +
1825 				"  @SuppressWarnings(\"unchecked\")\n" +
1826 				"  private static Func<Integer> read(byte[] bytes) throws Exception {\n" +
1827 				"    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);\n" +
1828 				"    try (ObjectInputStream ois = new ObjectInputStream(bis)) {\n" +
1829 				"      return (Func<Integer>) ois.readObject();\n" +
1830 				"    }\n" +
1831 				"  }\n" +
1832 				"  private static byte[] write(Func<Integer> func) throws Exception {\n" +
1833 				"    ByteArrayOutputStream bos = new ByteArrayOutputStream();\n" +
1834 				"    System.out.println(func.get());\n" +
1835 				"    try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {\n" +
1836 				"      oos.writeObject(func);//42\n" +
1837 				"    }\n" +
1838 				"    return bos.toByteArray();\n" +
1839 				"  }\n" +
1840 				"}"
1841 		},
1842 		"1\n" +
1843 		"2",
1844 		null,true,
1845 		new String[]{"-Ddummy"});
1846 	}
testbug494487()1847 	public void testbug494487() {
1848 		Map options = getCompilerOptions();
1849 		options.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE);
1850 		this.runConformTest(
1851 			new String[]{
1852 				"Test.java",
1853 				"import java.io.IOException;\n" +
1854 				"import java.io.Serializable;\n" +
1855 				"public class Test {\n" +
1856 				"  class AnException extends Exception {\n" +
1857 				"  }\n" +
1858 				"  class Asd {\n" +
1859 				"    public Asd(String asd) { data = asd; }\n" +
1860 				"    private final String data;\n" +
1861 				"    @Override\n" +
1862 				"    public String toString() {\n" +
1863 				"      return data;\n" +
1864 				"    }\n" +
1865 				"  }\n" +
1866 				"  public interface Test1 extends Serializable {\n" +
1867 				"    void test() throws IOException;\n" +
1868 				"  }\n" +
1869 				"  public interface Test2 {\n" +
1870 				"    void test() throws AnException;\n" +
1871 				"  }\n" +
1872 				"  public void test1( Test1 test ) {\n" +
1873 				"    try {\n" +
1874 				"      test.test();\n" +
1875 				"    } catch( IOException e ) {\n" +
1876 				"      e.printStackTrace();\n" +
1877 				"    }\n" +
1878 				"  }\n" +
1879 				"  public void test2( Test2 test ) {\n" +
1880 				"    try {\n" +
1881 				"      test.test();\n" +
1882 				"    } catch( AnException e ) {\n" +
1883 				"      System.out.println( e );\n" +
1884 				"    }\n" +
1885 				"  }\n" +
1886 				"  public void lambdas() {\n" +
1887 				"    test1( () -> System.out.println( \"test a\" ) );\n" +
1888 				"    test1( () -> System.out.println( \"test b\" ) );\n" +
1889 				"    test2( () -> System.out.println( \"test c\" ) );\n" +
1890 				"    test2( () -> System.out.println( \"test d\" ) );\n" +
1891 				"  }\n" +
1892 				"  public void print( CharSequence a, String b, long c ) {\n" +
1893 				"    System.out.println( a );\n" +
1894 				"    System.out.println( b );\n" +
1895 				"    System.out.println( c );\n" +
1896 				"  }\n" +
1897 				"  public void filler() {\n" +
1898 				"    System.out.println( \"Now we need to get this class file closer to 3000 bytes boundary\" );\n" +
1899 				"    filler1();\n" +
1900 				"    filler2();\n" +
1901 				"    filler3();\n" +
1902 				"    filler4();\n" +
1903 				"    filler5();\n" +
1904 				"    filler6();\n" +
1905 				"    filler7();\n" +
1906 				"    filler8();\n" +
1907 				"    filler9();\n" +
1908 				"    filler10();\n" +
1909 				"    filler11();\n" +
1910 				"    filler12();\n" +
1911 				"    filler13();\n" +
1912 				"    filler14();\n" +
1913 				"    filler15();\n" +
1914 				"    filler16();\n" +
1915 				"    filler17();\n" +
1916 				"    filler18();\n" +
1917 				"    filler19();\n" +
1918 				"    filler20();\n" +
1919 				"    filler21();\n" +
1920 				"    filler22();\n" +
1921 				"    filler23();\n" +
1922 				"    filler24();\n" +
1923 				"    filler25();\n" +
1924 				"    filler26();\n" +
1925 				"    filler27();\n" +
1926 				"    filler28();\n" +
1927 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1928 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1929 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1930 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1931 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1932 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1933 				"  }\n" +
1934 				"  private void filler28() {\n" +
1935 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1936 				"  }\n" +
1937 				"  private void filler27() {\n" +
1938 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1939 				"  }\n" +
1940 				"  private void filler26() {\n" +
1941 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1942 				"  }\n" +
1943 				"  private void filler25() {\n" +
1944 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1945 				"  }\n" +
1946 				"  private void filler24() {\n" +
1947 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1948 				"  }\n" +
1949 				"  private void filler23() {\n" +
1950 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1951 				"  }\n" +
1952 				"  private void filler22() {\n" +
1953 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1954 				"  }\n" +
1955 				"  private void filler21() {\n" +
1956 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1957 				"  }\n" +
1958 				"  private void filler20() {\n" +
1959 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1960 				"  }\n" +
1961 				"  private void filler19() {\n" +
1962 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1963 				"  }\n" +
1964 				"  private void filler18() {\n" +
1965 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1966 				"  }\n" +
1967 				"  private void filler17() {\n" +
1968 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1969 				"  }\n" +
1970 				"  private void filler16() {\n" +
1971 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1972 				"  }\n" +
1973 				"  private void filler15() {\n" +
1974 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1975 				"  }\n" +
1976 				"  private void filler14() {\n" +
1977 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1978 				"  }\n" +
1979 				"  private void filler13() {\n" +
1980 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1981 				"  }\n" +
1982 				"  private void filler12() {\n" +
1983 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1984 				"  }\n" +
1985 				"  private void filler11() {\n" +
1986 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1987 				"  }\n" +
1988 				"  private void filler10() {\n" +
1989 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1990 				"  }\n" +
1991 				"  private void filler9() {\n" +
1992 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1993 				"  }\n" +
1994 				"  private void filler8() {\n" +
1995 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1996 				"  }\n" +
1997 				"  private void filler7() {\n" +
1998 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
1999 				"  }\n" +
2000 				"  private void filler6() {\n" +
2001 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
2002 				"  }\n" +
2003 				"  private void filler5() {\n" +
2004 				"    print( c.toString(), d.toString(), System.currentTimeMillis() );\n" +
2005 				"  }\n" +
2006 				"  private void filler4() {\n" +
2007 				"    print( a.toString(), b.toString(), System.currentTimeMillis() );\n" +
2008 				"  }\n" +
2009 				"  private void filler3() {\n" +
2010 				"    print( \"a\", System.getenv( \"asd\" ), System.currentTimeMillis() );\n" +
2011 				"  }\n" +
2012 				"  private void filler2() {\n" +
2013 				"    print( \"a\", System.lineSeparator(), System.currentTimeMillis() );\n" +
2014 				"  }\n" +
2015 				"  private void filler1() {\n" +
2016 				"    print( \"a\", \"b\", System.currentTimeMillis() );\n" +
2017 				"  }\n" +
2018 				"  private final Asd a = new Asd(\"a\");\n" +
2019 				"  private final Asd b = new Asd(\"b\");\n" +
2020 				"  private final Asd c = new Asd(\"c\");\n" +
2021 				"  private final Asd d = new Asd(\"d\");\n" +
2022 				"}\n"
2023 		},
2024 		options);
2025 	}
testbug497879()2026 	public void testbug497879() {
2027 		this.runConformTest(
2028 			new String[]{
2029 				"LambdaSerializationTest.java",
2030 				"import java.io.ByteArrayInputStream;\n" +
2031 				"import java.io.ByteArrayOutputStream;\n" +
2032 				"import java.io.IOException;\n" +
2033 				"import java.io.ObjectInputStream;\n" +
2034 				"import java.io.ObjectOutputStream;\n" +
2035 				"import java.io.Serializable;\n" +
2036 				"import java.util.ArrayList;\n" +
2037 				"import java.util.List;\n" +
2038 				"import java.util.function.Supplier;\n" +
2039 				"public class LambdaSerializationTest {\n" +
2040 				"    interface SerializableSupplier<T> extends Supplier<T>, Serializable {}\n" +
2041 				"    public static void constructorReferenceSerialization() throws IOException, ClassNotFoundException {\n" +
2042 				"        SerializableSupplier<List<?>> function = ArrayList::new; //Collections::emptyList;\n" +
2043 				"        Object result = serializeDeserialize(function);\n" +
2044 				"        Class<?>[] infs = result.getClass().getInterfaces();\n" +
2045 				"        for(int i = 0; i < infs.length; i++) {\n" +
2046 				"            System.out.println(infs[i]);\n" +
2047 				"        }\n" +
2048 				"    }\n" +
2049 				"    private static Object serializeDeserialize(Object obj) throws IOException, ClassNotFoundException {\n" +
2050 				"        try (\n" +
2051 				"            ByteArrayOutputStream buffer = new ByteArrayOutputStream(); //\n" +
2052 				"            ObjectOutputStream output = new ObjectOutputStream(buffer)) {\n" +
2053 				"            output.writeObject(obj);\n" +
2054 				"            try (ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) {\n" +
2055 				"                return input.readObject();\n" +
2056 				"            }\n" +
2057 				"        }\n" +
2058 				"    }\n" +
2059 				"    public static void main(String[] args) {\n" +
2060 				"		try {\n" +
2061 				"			LambdaSerializationTest.constructorReferenceSerialization();\n" +
2062 				"		} catch (ClassNotFoundException | IOException e) {\n" +
2063 				"			// TODO Auto-generated catch block\n" +
2064 				"			e.printStackTrace();\n" +
2065 				"		}\n" +
2066 				"	}\n" +
2067 				"}"
2068 		},
2069 		"interface LambdaSerializationTest$SerializableSupplier",
2070 		null,true,
2071 		new String[]{"-Ddummy"});
2072 	}
testbug497879a()2073 	public void testbug497879a() {
2074 		this.runConformTest(
2075 			new String[]{
2076 				"LambdaSerializationTest.java",
2077 				"import java.io.ByteArrayInputStream;\n" +
2078 				"import java.io.ByteArrayOutputStream;\n" +
2079 				"import java.io.IOException;\n" +
2080 				"import java.io.ObjectInputStream;\n" +
2081 				"import java.io.ObjectOutputStream;\n" +
2082 				"import java.io.Serializable;\n" +
2083 				"import java.util.ArrayList;\n" +
2084 				"import java.util.List;\n" +
2085 				"import java.util.function.Supplier;\n" +
2086 				"public class LambdaSerializationTest {\n" +
2087 				"    interface SerializableSupplier<T> extends Supplier<T>, Serializable {}\n" +
2088 				"    static class Junk {\n" +
2089 				"    	private Junk() {}\n" +
2090 				"    }\n" +
2091 				"    public static void constructorReferenceSerialization() throws IOException, ClassNotFoundException {\n" +
2092 				"        SerializableSupplier<Junk> function = Junk::new;\n" +
2093 				"        Object result = serializeDeserialize(function);\n" +
2094 				"        Class<?>[] infs = result.getClass().getInterfaces();\n" +
2095 				"        for(int i = 0; i < infs.length; i++) {\n" +
2096 				"            System.out.println(infs[i]);\n" +
2097 				"        }\n" +
2098 				"    }\n" +
2099 				"    private static Object serializeDeserialize(Object obj) throws IOException, ClassNotFoundException {\n" +
2100 				"        try (\n" +
2101 				"            ByteArrayOutputStream buffer = new ByteArrayOutputStream(); //\n" +
2102 				"            ObjectOutputStream output = new ObjectOutputStream(buffer)) {\n" +
2103 				"            output.writeObject(obj);\n" +
2104 				"            try (ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) {\n" +
2105 				"                return input.readObject();\n" +
2106 				"            }\n" +
2107 				"        }\n" +
2108 				"    }\n" +
2109 				"    public static void main(String[] args) {\n" +
2110 				"		try {\n" +
2111 				"			LambdaSerializationTest.constructorReferenceSerialization();\n" +
2112 				"		} catch (ClassNotFoundException | IOException e) {\n" +
2113 				"			// TODO Auto-generated catch block\n" +
2114 				"			e.printStackTrace();\n" +
2115 				"		}\n" +
2116 				"	}\n" +
2117 				"}"
2118 		},
2119 		"interface LambdaSerializationTest$SerializableSupplier",
2120 		null,true,
2121 		new String[]{"-Ddummy"});
2122 	}
testbug497879b()2123 	public void testbug497879b() {
2124 		this.runConformTest(
2125 			new String[]{
2126 				"LambdaSerializationTest.java",
2127 				"import java.io.ByteArrayInputStream;\n" +
2128 				"import java.io.ByteArrayOutputStream;\n" +
2129 				"import java.io.IOException;\n" +
2130 				"import java.io.ObjectInputStream;\n" +
2131 				"import java.io.ObjectOutputStream;\n" +
2132 				"import java.io.Serializable;\n" +
2133 				"import java.util.ArrayList;\n" +
2134 				"import java.util.List;\n" +
2135 				"import java.util.function.Supplier;\n" +
2136 				"public class LambdaSerializationTest {\n" +
2137 				"    interface SerializableSupplier<T> extends Serializable {\n" +
2138 				"        T get(int count);\n" +
2139 				"    }\n" +
2140 				"    public static void constructorReferenceSerialization() throws IOException, ClassNotFoundException {\n" +
2141 				"        SerializableSupplier<List[]> function = ArrayList[]::new;\n" +
2142 				"        Object result = serializeDeserialize(function);\n" +
2143 				"        Class<?>[] infs = result.getClass().getInterfaces();\n" +
2144 				"        for(int i = 0; i < infs.length; i++) {\n" +
2145 				"            System.out.println(infs[i]);\n" +
2146 				"        }\n" +
2147 				"    }\n" +
2148 				"    private static Object serializeDeserialize(Object obj) throws IOException, ClassNotFoundException {\n" +
2149 				"        try (\n" +
2150 				"            ByteArrayOutputStream buffer = new ByteArrayOutputStream(); //\n" +
2151 				"            ObjectOutputStream output = new ObjectOutputStream(buffer)) {\n" +
2152 				"            output.writeObject(obj);\n" +
2153 				"            try (ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) {\n" +
2154 				"                return input.readObject();\n" +
2155 				"            }\n" +
2156 				"        }\n" +
2157 				"    }\n" +
2158 				"    public static void main(String[] args) {\n" +
2159 				"		try {\n" +
2160 				"			LambdaSerializationTest.constructorReferenceSerialization();\n" +
2161 				"		} catch (ClassNotFoundException | IOException e) {\n" +
2162 				"			// TODO Auto-generated catch block\n" +
2163 				"			e.printStackTrace();\n" +
2164 				"		}\n" +
2165 				"	}\n" +
2166 				"}"
2167 		},
2168 		"interface LambdaSerializationTest$SerializableSupplier",
2169 		null,true,
2170 		new String[]{"-Ddummy"});
2171 	}
testbug503118()2172 	public void testbug503118() {
2173 		this.runConformTest(
2174 			new String[]{
2175 				"lambdabug/App.java",
2176 				"package lambdabug;\n" +
2177 				"import java.io.ByteArrayInputStream;\n" +
2178 				"import java.io.ByteArrayOutputStream;\n" +
2179 				"import java.io.ObjectInputStream;\n" +
2180 				"import java.io.ObjectOutputStream;\n" +
2181 				"import java.io.Serializable;\n" +
2182 				"import java.util.function.Function;\n" +
2183 				"public class App {\n" +
2184 				"	public static interface SerialFunction<T, R> extends Function<T, R>, Serializable {\n" +
2185 				"	}\n" +
2186 				"	public static interface TestInterface extends Serializable {\n" +
2187 				"		public Integer method(Integer i);\n" +
2188 				"	}\n" +
2189 				"	public static class TestClass implements TestInterface {\n" +
2190 				"		private static final long serialVersionUID = 1L;\n" +
2191 				"		@Override\n" +
2192 				"		public Integer method(Integer i) {\n" +
2193 				"			return i;\n" +
2194 				"		}\n" +
2195 				"	}\n" +
2196 				"	public static void main(String[] args) throws Exception {\n" +
2197 				"		TestInterface testService = getService();\n" +
2198 				"		SerialFunction<Integer, Integer> sf = testService::method;\n" +
2199 				"		ByteArrayOutputStream bos = new ByteArrayOutputStream();\n" +
2200 				"		new ObjectOutputStream(bos).writeObject(sf);\n" +
2201 				"		Object o = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())).readObject();\n" +
2202 				"		System.out.println(o.getClass().getInterfaces()[0]);\n" +
2203 				"	}\n" +
2204 				"	private static TestInterface getService() {\n" +
2205 				"		return new TestClass();\n" +
2206 				"	}\n" +
2207 				"}\n"
2208 		},
2209 		"interface lambdabug.App$SerialFunction",
2210 		null,true,
2211 		new String[]{"-Ddummy"});
2212 	}
testbug507011()2213 	public void testbug507011() {
2214 		this.runConformTest(
2215 			new String[]{
2216 				"VerifyErrorDerived.java",
2217 				"import java.io.Serializable;\n" +
2218 				"import java.util.function.Function;\n" +
2219 				"public class VerifyErrorDerived extends VerifyErrorBase {\n" +
2220 				"	public static void main(String [] args) {\n" +
2221 				"		System.out.println(\"hello world\");\n" +
2222 				"	}\n" +
2223 				"	public int derivedMethod(String param) {\n" +
2224 				"		SerializableFunction<String, Integer> f = super::baseMethod;\n" +
2225 				"		return f.apply(param);\n" +
2226 				"	}\n" +
2227 				"}\n" +
2228 				"interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}",
2229 				"VerifyErrorBase.java",
2230 				"public class VerifyErrorBase {\n" +
2231 				"	public int baseMethod(String param) {\n" +
2232 				"		return 7;\n" +
2233 				"	}\n" +
2234 				"}\n"
2235 		},
2236 		"hello world",
2237 		null,true,
2238 		new String[]{"-Ddummy"});
2239 	}
testbug509782()2240 	public void testbug509782() {
2241 		this.runConformTest(
2242 			new String[]{
2243 				"compilertest/BaseType.java",
2244 				"package compilertest;\n" +
2245 				"import java.io.ByteArrayInputStream;\n" +
2246 				"import java.io.ByteArrayOutputStream;\n" +
2247 				"import java.io.ObjectInputStream;\n" +
2248 				"import java.io.ObjectOutputStream;\n" +
2249 				"import java.io.Serializable;\n" +
2250 				"import compilertest.sub.SubType;\n" +
2251 				"public class BaseType implements Serializable {\n" +
2252 				"    protected void doSomething() {\n" +
2253 				"    }\n" +
2254 				"    public static void main(String[] args) throws Exception {\n" +
2255 				"        SubType instance = new SubType();\n" +
2256 				"        ByteArrayOutputStream bs = new ByteArrayOutputStream();\n" +
2257 				"        ObjectOutputStream out = new ObjectOutputStream(bs);\n" +
2258 				"        out.writeObject(instance);\n" +
2259 				"        byte[] data = bs.toByteArray();\n" +
2260 				"        ObjectInputStream in = new ObjectInputStream(\n" +
2261 				"                new ByteArrayInputStream(data));\n" +
2262 				"        in.readObject();\n" +
2263 				"        System.out.println(\"Done\");\n" +
2264 				"    }\n" +
2265 				"}",
2266 				"compilertest/sub/SubType.java",
2267 				"package compilertest.sub;\n" +
2268 				"import java.io.Serializable;\n" +
2269 				"import compilertest.BaseType;\n" +
2270 				"public class SubType extends BaseType {\n" +
2271 				"    Runnable task = (Runnable & Serializable) this::doSomething;\n" +
2272 				"}\n"
2273 		},
2274 		"Done",
2275 		null,true,
2276 		new String[]{"-Ddummy"});
2277 	}
2278 	// ---
2279 
checkExpected(String expected, String actual)2280 	private void checkExpected(String expected, String actual) {
2281 		if (!expected.equals(actual)) {
2282 			printIt(actual);
2283 		}
2284 		assertEquals(expected,actual);
2285 	}
2286 
2287 	/**
2288 	 * Print a piece of text with the necessary extra quotes and newlines so that it can be cut/pasted into
2289 	 * the test source file.
2290 	 */
printIt(String text)2291 	private void printIt(String text) {
2292 		String quotedText = text;
2293 		if (!quotedText.startsWith("\"")) {
2294 			quotedText = "\""+quotedText.replaceAll("\n", "\\\\n\"+\n\"");
2295 			quotedText = quotedText.substring(0,quotedText.length()-3);
2296 		}
2297 		System.out.println(quotedText);
2298 	}
2299 
2300 	/**
2301 	 * Print the bootstrap methods attribute in a very similar fashion to javap for checking.
2302 	 * Unlike javap the constant pool indexes are not included, to make the test a little less
2303 	 * fragile.
2304 	 */
printBootstrapMethodsAttribute(String filepath)2305 	private String printBootstrapMethodsAttribute(String filepath) {
2306 		IClassFileReader cfr = ToolFactory.createDefaultClassFileReader(filepath, IClassFileReader.CLASSFILE_ATTRIBUTES);
2307 		BootstrapMethodsAttribute bootstrapMethodsAttribute = null;
2308 		IClassFileAttribute[] attrs = cfr.getAttributes();
2309 		for (int i=0,max=attrs.length;i<max;i++) {
2310 			if (new String(attrs[i].getAttributeName()).equals("BootstrapMethods")) {
2311 				bootstrapMethodsAttribute = (BootstrapMethodsAttribute)attrs[i];
2312 			}
2313 		}
2314 		if (bootstrapMethodsAttribute==null) {
2315 			return "";
2316 		}
2317 		IConstantPool cp = cfr.getConstantPool();
2318 		StringBuffer sb = new StringBuffer();
2319 		int bmaLength = bootstrapMethodsAttribute.getBootstrapMethodsLength();
2320 		for (int i=0;i<bmaLength;i++) {
2321 			IBootstrapMethodsEntry entry = bootstrapMethodsAttribute.getBootstrapMethods()[i];
2322 			int mr = entry.getBootstrapMethodReference();
2323 			IConstantPoolEntry2 icpe = (IConstantPoolEntry2)cfr.getConstantPool().decodeEntry(mr);
2324 
2325 			sb.append(i).append(": ").append(formatReferenceKind(icpe.getReferenceKind()));
2326 			sb.append(" ").append(format(cp,icpe.getReferenceIndex()));
2327 			sb.append("\n");
2328 			int[] args = entry.getBootstrapArguments();
2329 			sb.append("  Method arguments:\n");
2330 			for (int a=0;a<args.length;a++) {
2331 				sb.append("    ").append(format(cp,args[a])).append("\n");
2332 			}
2333 		}
2334 		return sb.toString();
2335 	}
2336 
printLambdaMethods(String filepath)2337 	private String printLambdaMethods(String filepath) {
2338 		IClassFileReader cfr = ToolFactory.createDefaultClassFileReader(filepath, IClassFileReader.METHOD_INFOS);
2339 		IMethodInfo[] methodInfos = cfr.getMethodInfos();
2340 		StringBuffer buf = new StringBuffer();
2341 		for (int i = 0, max = methodInfos.length; i < max; i++) {
2342 			IMethodInfo methodInfo = methodInfos[i];
2343 			if (!new String(methodInfo.getName()).startsWith("lambda"))
2344 				continue;
2345 			int accessFlags = methodInfo.getAccessFlags();
2346 			if (Modifier.isStatic(accessFlags)) {
2347 				buf.append("static ");
2348 			}
2349 			buf.append(methodInfo.getName());
2350 			buf.append(methodInfo.getDescriptor());
2351 			buf.append("\n");
2352 		}
2353 		return buf.toString();
2354 	}
2355 
formatReferenceKind(int kind)2356 	String formatReferenceKind(int kind) {
2357 		switch (kind) {
2358 			case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic:
2359 				return "invokestatic";
2360 			default:
2361 				throw new IllegalStateException("nyi for "+kind);
2362 		}
2363 	}
2364 
format(IConstantPool cp, int entryNumber)2365 	String format(IConstantPool cp, int entryNumber) {
2366 		IConstantPoolEntry entry = cp.decodeEntry(entryNumber);
2367 		if (entry == null) {
2368 			return "null";
2369 		}
2370 		switch (entry.getKind()) {
2371 			case IConstantPoolConstant.CONSTANT_Integer:
2372 				return Integer.toString(entry.getIntegerValue());
2373 			case IConstantPoolConstant.CONSTANT_Utf8:
2374 				return new String(entry.getUtf8Value());
2375 			case IConstantPoolConstant.CONSTANT_Methodref:
2376 				return new String(entry.getClassName())+"."+new String(entry.getMethodName())+":"+new String(entry.getMethodDescriptor());
2377 			case IConstantPoolConstant.CONSTANT_MethodHandle:
2378 				IConstantPoolEntry2 entry2 = (IConstantPoolEntry2)entry;
2379 				return formatReferenceKind(entry2.getReferenceKind())+" "+format(cp,entry2.getReferenceIndex());
2380 			case IConstantPoolConstant.CONSTANT_MethodType:
2381 				return format(cp,((IConstantPoolEntry2)entry).getDescriptorIndex());
2382 			case IConstantPoolConstant.CONSTANT_Class:
2383 				return new String(entry.getClassInfoName());
2384 			default:
2385 					throw new IllegalStateException("nyi for "+entry.getKind());
2386 		}
2387 	}
2388 
2389 }
2390 
2391