--- /dev/null 2019-03-11 09:03:40.980007338 -0400 +++ new/test/jdk/java/lang/instrument/RedefineAddDeleteMethod/DeleteMethodHandle/MethodHandleDeletedMethod.java 2019-03-12 18:04:09.467955436 -0400 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8181171 8210457 + * @summary Break ResolvedMethodTable with redefined nest class. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * @compile ../../NamedBuffer.java + * @compile redef/Xost.java + * @run main RedefineClassHelper + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=debug,membername+table=debug MethodHandleDeletedMethod + */ + +import java.io.File; +import java.io.FileInputStream; +import java.lang.invoke.*; + +class Host { + static MethodHandle fooMH; + + static class A { + private static void foo() { System.out.println("OLD foo called"); } + } + static void bar() throws NoSuchMethodError { + A.foo(); + } + static void barMH() throws Throwable { + fooMH.invokeExact(); + } + + public static void reresolve() throws Throwable { + fooMH = MethodHandles.lookup().findStatic(A.class, "foo", MethodType.methodType(void.class)); + } + + static { + try { + fooMH = MethodHandles.lookup().findStatic(A.class, "foo", MethodType.methodType(void.class)); + } catch (ReflectiveOperationException ex) { + } + } +} + +public class MethodHandleDeletedMethod { + + static final String DEST = System.getProperty("test.classes"); + static final boolean VERBOSE = false; + + private static byte[] bytesForHostClass(char replace) throws Throwable { + return NamedBuffer.bytesForHostClass(replace, "Host$A"); + } + + public static void main(java.lang.String[] unused) throws Throwable { + Host h = new Host(); + h.bar(); + h.barMH(); + byte[] buf = bytesForHostClass('X'); + RedefineClassHelper.redefineClass(Host.A.class, buf); + try { + h.bar(); // call deleted Method directly + throw new RuntimeException("Failed, expected NSME"); + } catch (NoSuchMethodError nsme) { + System.out.println("Received expected NSME"); + } + try { + h.barMH(); // call through MethodHandle for deleted Method + throw new RuntimeException("Failed, expected NSME"); + } catch (NoSuchMethodError nsme) { + System.out.println("Received expected NSME"); + } + System.out.println("Passed."); + } +}