1 /*
2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 import sun.hotspot.WhiteBox;
26 
27 // package access top-level class to avoid problem with RedefineClassHelper
28 // and nested types.
29 class RedefineBasic_B {
okToCallBeforeRedefine()30     public static void okToCallBeforeRedefine() {
31         System.out.println("okToCallBeforeRedefine");
32     }
okToCallAfterRedefine()33     public static void okToCallAfterRedefine() {
34         throw new RuntimeException("okToCallAfterRedefine is called before redefinition, test failed");
35     }
36 }
37 
38 public class RedefineBasic {
39 
40     public static String newB =
41         " class RedefineBasic_B { " +
42         " public static void okToCallBeforeRedefine() { " +
43         "    throw new RuntimeException(\"newB: okToCallBeforeRedefine is " +
44         "    called after redefinition, test failed\"); }" +
45         " public static void okToCallAfterRedefine() { " +
46         "     System.out.println(\"newB: okToCallAfterRedefine\"); } " +
47         " } ";
48 
49 
50 
51     static class SubclassOfB extends RedefineBasic_B {
testAfterRedefine()52         public static void testAfterRedefine() {
53             RedefineBasic_B.okToCallAfterRedefine();
54         }
55     }
56 
57     class Subclass2OfB extends RedefineBasic_B {
testAfterRedefine()58         public void testAfterRedefine() {
59             super.okToCallAfterRedefine();
60         }
61     }
62 
63     // verify that a given class is shared, report error if necessary
64     public static void
verifyClassIsShared(WhiteBox wb, Class c)65     verifyClassIsShared(WhiteBox wb, Class c) throws Exception {
66         if (!wb.isSharedClass(c)) {
67             throw new RuntimeException(
68             "This class should be shared but isn't: " + c.getName());
69         } else {
70             System.out.println("The class is shared as expected: " +
71                 c.getName());
72         }
73     }
74 
main(String[] args)75     public static void main(String[] args) throws Exception {
76         WhiteBox wb = WhiteBox.getWhiteBox();
77 
78         verifyClassIsShared(wb, RedefineBasic.class);
79         verifyClassIsShared(wb, RedefineBasic_B.class);
80         verifyClassIsShared(wb, SubclassOfB.class);
81         verifyClassIsShared(wb, Subclass2OfB.class);
82 
83         // (1) Test case: verify that original B works as expected
84         // and that redefined B is shared and works as expected,
85         // with new behavior
86         RedefineBasic_B.okToCallBeforeRedefine();
87         RedefineClassHelper.redefineClass(RedefineBasic_B.class, newB);
88         verifyClassIsShared(wb, RedefineBasic_B.class);
89         RedefineBasic_B.okToCallAfterRedefine();
90 
91         // Static subclass of the super:
92         // 1. Make sure it is still shared
93         // 2. and it calls the correct super (the redefined one)
94         verifyClassIsShared(wb, SubclassOfB.class);
95         SubclassOfB.testAfterRedefine();
96 
97         // Same as above, but for non-static class
98         verifyClassIsShared(wb, Subclass2OfB.class);
99         RedefineBasic thisTest = new RedefineBasic();
100         thisTest.testSubclass2OfB();
101     }
102 
testSubclass2OfB()103     public void testSubclass2OfB() {
104         Subclass2OfB sub = new Subclass2OfB();
105         sub.testAfterRedefine();
106     }
107 }
108