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 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 try { 67 Thread.sleep(1000); 68 } catch (InterruptedException e) { 69 System.out.println("Main thread interrupted, continuing execution."); 70 } 71 } 72 73 if (privateFinalizeInvoked) { 74 throw new RuntimeException("private finalize method invoked"); 75 } 76 if (finalizedCount.get() != (count+1)) { 77 throw new RuntimeException("Unexpected count=" + finalizedCount + 78 " expected=" + (count+1)); 79 } 80 if (finalizedSum.get() != (sum+expected)) { 81 throw new RuntimeException("Unexpected sum=" + finalizedSum + 82 " prev=" + sum + " value=" + expected); 83 } 84 } 85 86 static void patchPrivateFinalize() throws IOException { 87 // patch the private f_nal_ze method name to "finalize" 88 String testClasses = System.getProperty("test.classes", "."); 89 Path p = Paths.get(testClasses, "FinalizeOverride$PrivateFinalize.class"); 90 byte[] bytes = Files.readAllBytes(p); 91 int len = "f_nal_ze".length(); 92 for (int i=0; i < bytes.length-len; i++) { 93 if (bytes[i] == 'f' && 94 bytes[i+1] == '_' && 95 bytes[i+2] == 'n' && 96 bytes[i+3] == 'a' && 97 bytes[i+4] == 'l' && 98 bytes[i+5] == '_' && 99 bytes[i+6] == 'z' && 100 bytes[i+7] == 'e') 101 { 102 // s%_%i% 103 bytes[i+1] = 'i'; 104 bytes[i+5] = 'i'; 105 break; 106 } 107 } 108 Files.write(p, bytes); 109 } 110 111 static class Base { 112 protected int value; 113 Base(int v) { 114 this.value = v; 115 } 116 int called() { 117 finalizedSum.addAndGet(value); 118 return value; 119 } 120 protected void finalize() { 121 System.out.println("Base.finalize() sum += " + called()); 122 finalizedCount.incrementAndGet(); 123 } 124 } 125 static class PublicFinalize extends Base { 126 PublicFinalize(int v) { 127 super(v); 128 } 129 public void finalize() { 130 finalizedSum.addAndGet(value * 100); 131 System.out.println("PublicFinalize.finalize() sum += " + called() + 132 "+"+value+"*100"); 133 finalizedCount.incrementAndGet(); 134 } 135 } 136 static class Subclass extends Base { 137 Subclass(int v) { 138 super(v); 139 } 140 protected void finalize() { 141 // no value added to sum 142 System.out.println("Subclass.finalize() sum += 0"); 143 finalizedCount.incrementAndGet(); 144 } 145 } 146 static class SubSubclass extends Subclass { 147 SubSubclass(int v) { 148 super(v); 149 } 150 protected final void finalize() { 151 finalizedSum.addAndGet(value); 152 System.out.println("SubSubclass.finalize() sum +=" +value); 153 finalizedCount.incrementAndGet(); 154 } 155 } 156 static class PrivateFinalize extends Base { 157 PrivateFinalize(int v) { 158 super(v); 159 } 160 private void f_nal_ze() { 161 // finalization catches any exception 162 System.out.println("Error: private finalize invoked!!"); 163 privateFinalizeInvoked = true; 164 finalizedCount.incrementAndGet(); 165 } 166 } 167 static class NoOverride extends PrivateFinalize { 168 NoOverride(int v) { 169 super(v); 170 } 171 } 172 }