/* * Copyright (c) 2016, 2018, 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. * */ import sun.hotspot.WhiteBox; // package access top-level class to avoid problem with RedefineClassHelper // and nested types. class RedefineBasic_B { public static void okToCallBeforeRedefine() { System.out.println("okToCallBeforeRedefine"); } public static void okToCallAfterRedefine() { throw new RuntimeException("okToCallAfterRedefine is called before redefinition, test failed"); } } public class RedefineBasic { public static String newB = " class RedefineBasic_B { " + " public static void okToCallBeforeRedefine() { " + " throw new RuntimeException(\"newB: okToCallBeforeRedefine is " + " called after redefinition, test failed\"); }" + " public static void okToCallAfterRedefine() { " + " System.out.println(\"newB: okToCallAfterRedefine\"); } " + " } "; static class SubclassOfB extends RedefineBasic_B { public static void testAfterRedefine() { RedefineBasic_B.okToCallAfterRedefine(); } } class Subclass2OfB extends RedefineBasic_B { public void testAfterRedefine() { super.okToCallAfterRedefine(); } } // verify that a given class is shared, report error if necessary public static void verifyClassIsShared(WhiteBox wb, Class c) throws Exception { if (!wb.isSharedClass(c)) { throw new RuntimeException( "This class should be shared but isn't: " + c.getName()); } else { System.out.println("The class is shared as expected: " + c.getName()); } } public static void main(String[] args) throws Exception { WhiteBox wb = WhiteBox.getWhiteBox(); verifyClassIsShared(wb, RedefineBasic.class); verifyClassIsShared(wb, RedefineBasic_B.class); verifyClassIsShared(wb, SubclassOfB.class); verifyClassIsShared(wb, Subclass2OfB.class); // (1) Test case: verify that original B works as expected // and that redefined B is shared and works as expected, // with new behavior RedefineBasic_B.okToCallBeforeRedefine(); RedefineClassHelper.redefineClass(RedefineBasic_B.class, newB); verifyClassIsShared(wb, RedefineBasic_B.class); RedefineBasic_B.okToCallAfterRedefine(); // Static subclass of the super: // 1. Make sure it is still shared // 2. and it calls the correct super (the redefined one) verifyClassIsShared(wb, SubclassOfB.class); SubclassOfB.testAfterRedefine(); // Same as above, but for non-static class verifyClassIsShared(wb, Subclass2OfB.class); RedefineBasic thisTest = new RedefineBasic(); thisTest.testSubclass2OfB(); } public void testSubclass2OfB() { Subclass2OfB sub = new Subclass2OfB(); sub.testAfterRedefine(); } }