1 /*
  2  * Copyright (c) 2014, 2019, 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  * @test
 26  * @bug 8055008 8197901 8010319
 27  * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
 28  * @requires vm.jvmti
 29  * @library /test/lib
 30  * @modules java.base/jdk.internal.misc
 31  * @modules java.compiler
 32  *          java.instrument
 33  *          jdk.jartool/sun.tools.jar
 34  * @compile --enable-preview -source ${jdk.version} RedefineRunningMethods.java
 35  * @run main RedefineClassHelper
 36  * @run main/othervm/timeout=180
 37  *         --enable-preview
 38  *         -javaagent:redefineagent.jar
 39  *         -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,class+loader+data=debug,safepoint+cleanup,gc+phases=debug:rt.log
 40  *         RedefineRunningMethods
 41  */
 42 
 43 
 44 // package access top-level class to avoid problem with RedefineClassHelper
 45 // and nested types.
 46 class RedefineRunningMethods_B {
 47     static int count1 = 0;
 48     static int count2 = 0;
 49     public static volatile boolean stop = false;
 50     static void localSleep() {
 51         try{
 52             Thread.currentThread().sleep(10);//sleep for 10 ms
 53         } catch(InterruptedException ie) {
 54         }
 55     }
 56 
 57     public static void infinite() {
 58         while (!stop) { count1++; localSleep(); }
 59     }
 60     public static void infinite_emcp() {
 61         while (!stop) { count2++; localSleep(); }
 62     }
 63 }
 64 
 65 public class RedefineRunningMethods {
 66 
 67     public static String newB =
 68                 "class RedefineRunningMethods_B {" +
 69                 "   static int count1 = 0;" +
 70                 "   static int count2 = 0;" +
 71                 "   public static volatile boolean stop = false;" +
 72                 "  static void localSleep() { " +
 73                 "    try{ " +
 74                 "      Thread.currentThread().sleep(10);" +
 75                 "    } catch(InterruptedException ie) { " +
 76                 "    } " +
 77                 " } " +
 78                 "   public static void infinite() { " +
 79                 "       System.out.println(\"infinite called\");" +
 80                 "   }" +
 81                 "   public static void infinite_emcp() { " +
 82                 "       while (!stop) { count2++; localSleep(); }" +
 83                 "   }" +
 84                 "}";
 85 
 86     public static String evenNewerB =
 87                 "class RedefineRunningMethods_B {" +
 88                 "   static int count1 = 0;" +
 89                 "   static int count2 = 0;" +
 90                 "   public static volatile boolean stop = false;" +
 91                 "  static void localSleep() { " +
 92                 "    try{ " +
 93                 "      Thread.currentThread().sleep(1);" +
 94                 "    } catch(InterruptedException ie) { " +
 95                 "    } " +
 96                 " } " +
 97                 "   public static void infinite() { }" +
 98                 "   public static void infinite_emcp() { " +
 99                 "       System.out.println(\"infinite_emcp now obsolete called\");" +
100                 "   }" +
101                 "}";
102 
103 
104     public static void main(String[] args) throws Exception {
105 
106         var t1 = Thread.ofPlatform().start(RedefineRunningMethods_B::infinite);
107         var t1v = Thread.ofVirtual().start(RedefineRunningMethods_B::infinite);
108         var t2 = Thread.ofPlatform().start(RedefineRunningMethods_B::infinite_emcp);
109         var t2v = Thread.ofVirtual().start(RedefineRunningMethods_B::infinite);
110 
111         RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
112 
113         System.gc();
114 
115         RedefineRunningMethods_B.infinite();
116 
117         // Start a thread with the second version of infinite_emcp running
118         var t3 = Thread.ofPlatform().start(RedefineRunningMethods_B::infinite_emcp);
119         var t3v = Thread.ofVirtual().start(RedefineRunningMethods_B::infinite_emcp);
120 
121 
122         for (int i = 0; i < 20 ; i++) {
123             String s = new String("some garbage");
124             System.gc();
125         }
126 
127         RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
128         System.gc();
129 
130         for (int i = 0; i < 20 ; i++) {
131             RedefineRunningMethods_B.infinite();
132             String s = new String("some garbage");
133             System.gc();
134         }
135 
136         RedefineRunningMethods_B.infinite_emcp();
137 
138         // purge should clean everything up.
139         RedefineRunningMethods_B.stop = true;
140 
141         for (int i = 0; i < 20 ; i++) {
142             RedefineRunningMethods_B.infinite();
143             String s = new String("some garbage");
144             System.gc();
145         }
146 /*
147         TODO uncomment, should be join added to orginal test?
148         t1.join();
149         t2.join();
150         t3.join();
151         t1v.join();
152         t2v.join();
153  */
154     }
155 }