1 /* 2 * Copyright (c) 2013, 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 import java.io.ByteArrayOutputStream; 25 import java.io.IOException; 26 import java.nio.file.Files; 27 import java.nio.file.Path; 28 import java.nio.file.Paths; 29 import java.util.concurrent.atomic.AtomicInteger; 30 31 /* @test 32 * @bug 8027351 8148940 33 * @summary Basic test of the finalize method 34 */ 35 36 public class FinalizeOverride { 37 // finalizedCount is incremented when the finalize method is invoked 38 private static AtomicInteger finalizedCount = new AtomicInteger(); 39 40 // finalizedSum and privateFinalizedInvoke are used to verify 41 // the right overrided finalize method is invoked 42 private static AtomicInteger finalizedSum = new AtomicInteger(); 43 private static volatile boolean privateFinalizeInvoked = false; 44 45 public static void main(String[] argvs) throws IOException { 46 patchPrivateFinalize(); 47 48 test(new Base(10), 10); 49 test(new Subclass(20), 0); 50 test(new SubSubclass(30), 30); 51 test(new PublicFinalize(40), 40*100+40); 52 test(new PrivateFinalize(50), 50); 53 test(new NoOverride(60), 60); 54 } 55 56 static void test(Object o, int expected) { 57 int count = finalizedCount.get(); 58 int sum = finalizedSum.get(); 59 privateFinalizeInvoked = false; 60 61 // force GC and finalization 62 o = null; 63 while (finalizedCount.get() != (count+1)) { 64 System.gc(); 65 System.runFinalization(); 66 // Running System.gc() and System.runFinalization() in a 67 // tight loop can trigger frequent safepointing that slows 68 // down the VM and, as a result, the test. (With the 69 // HotSpot VM, the effect of frequent safepointing is 70 // especially noticeable if the test is run with the 71 // -Xcomp flag.) Sleeping for a second after every 72 // garbage collection and finalization cycle gives the VM 73 // time to make progress. 74 try { 75 Thread.sleep(1000); 76 } catch (InterruptedException e) { 77 System.out.println("Main thread interrupted, continuing execution."); 78 } 79 } 80 81 if (privateFinalizeInvoked) { 82 throw new RuntimeException("private finalize method invoked"); 83 } 84 if (finalizedCount.get() != (count+1)) { 85 throw new RuntimeException("Unexpected count=" + finalizedCount + 86 " expected=" + (count+1)); 87 } 88 if (finalizedSum.get() != (sum+expected)) { 89 throw new RuntimeException("Unexpected sum=" + finalizedSum + 90 " prev=" + sum + " value=" + expected); 91 } 92 } 93 94 static void patchPrivateFinalize() throws IOException { 95 // patch the private f_nal_ze method name to "finalize" 96 String testClasses = System.getProperty("test.classes", "."); 97 Path p = Paths.get(testClasses, "FinalizeOverride$PrivateFinalize.class"); 98 byte[] bytes = Files.readAllBytes(p); 99 int len = "f_nal_ze".length(); 100 for (int i=0; i < bytes.length-len; i++) { 101 if (bytes[i] == 'f' && 102 bytes[i+1] == '_' && 103 bytes[i+2] == 'n' && 104 bytes[i+3] == 'a' && 105 bytes[i+4] == 'l' && 106 bytes[i+5] == '_' && 107 bytes[i+6] == 'z' && 108 bytes[i+7] == 'e') 109 { 110 // s%_%i% 111 bytes[i+1] = 'i'; 112 bytes[i+5] = 'i'; 113 break; 114 } 115 } 116 Files.write(p, bytes); 117 } 118 119 static class Base { 120 protected int value; 121 Base(int v) { 122 this.value = v; 123 } 124 int called() { 125 finalizedSum.addAndGet(value); 126 return value; 127 } 128 protected void finalize() { 129 System.out.println("Base.finalize() sum += " + called()); 130 finalizedCount.incrementAndGet(); 131 } 132 } 133 static class PublicFinalize extends Base { 134 PublicFinalize(int v) { 135 super(v); 136 } 137 public void finalize() { 138 finalizedSum.addAndGet(value * 100); 139 System.out.println("PublicFinalize.finalize() sum += " + called() + 140 "+"+value+"*100"); 141 finalizedCount.incrementAndGet(); 142 } 143 } 144 static class Subclass extends Base { 145 Subclass(int v) { 146 super(v); 147 } 148 protected void finalize() { 149 // no value added to sum 150 System.out.println("Subclass.finalize() sum += 0"); 151 finalizedCount.incrementAndGet(); 152 } 153 } 154 static class SubSubclass extends Subclass { 155 SubSubclass(int v) { 156 super(v); 157 } 158 protected final void finalize() { 159 finalizedSum.addAndGet(value); 160 System.out.println("SubSubclass.finalize() sum +=" +value); 161 finalizedCount.incrementAndGet(); 162 } 163 } 164 static class PrivateFinalize extends Base { 165 PrivateFinalize(int v) { 166 super(v); 167 } 168 private void f_nal_ze() { 169 // finalization catches any exception 170 System.out.println("Error: private finalize invoked!!"); 171 privateFinalizeInvoked = true; 172 finalizedCount.incrementAndGet(); 173 } 174 } 175 static class NoOverride extends PrivateFinalize { 176 NoOverride(int v) { 177 super(v); 178 } 179 } 180 }