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