/* * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8276422 * @summary add command-line option to disable finalization * @run main/othervm FinalizationOption yes * @run main/othervm --finalization=enabled FinalizationOption yes * @run main/othervm --finalization=disabled FinalizationOption no */ public class FinalizationOption { static volatile boolean finalizerWasCalled = false; @SuppressWarnings("deprecation") protected void finalize() { finalizerWasCalled = true; } static void create() { new FinalizationOption(); } /** * Checks whether the finalizer thread is or is not running. The finalizer thread * is a thread in the root thread group whose named is "Finalizer". * @param expected boolean indicating whether a finalizer thread should exist * @return boolean indicating whether the expectation was met */ static boolean checkFinalizerThread(boolean expected) { ThreadGroup root = Thread.currentThread().getThreadGroup(); for (ThreadGroup parent = root; parent != null; root = parent, parent = root.getParent()) ; int nt = 100; Thread[] threads; while (true) { threads = new Thread[nt]; nt = root.enumerate(threads); if (nt < threads.length) break; threads = new Thread[nt + 100]; } Thread ft = null; for (int i = 0; i < nt; i++) { if ("Finalizer".equals(threads[i].getName())) { ft = threads[i]; break; } } String msg = (ft == null) ? "(none)" : ft.toString(); boolean passed = (ft != null) == expected; System.out.printf("Finalizer thread. Expected: %s Actual: %s %s%n", expected, msg, passed ? "Passed." : "FAILED!"); return passed; } /** * Checks whether there was a call to the finalize() method. * @param expected boolean whether finalize() should be called * @return boolean indicating whether the expecation was met */ static boolean checkFinalizerCalled(boolean expected) { create(); for (int i = 0; i < 100; i++) { System.gc(); try { Thread.sleep(10L); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } if (finalizerWasCalled) { break; } } boolean passed = (expected == finalizerWasCalled); System.out.printf("Call to finalize(). Expected: %s Actual: %s %s%n", expected, finalizerWasCalled, passed ? "Passed." : "FAILED!"); return passed; } public static void main(String[] args) { boolean finalizationEnabled = switch (args[0]) { case "yes" -> true; case "no" -> false; default -> { throw new AssertionError("usage: FinalizationOption yes|no"); } }; boolean threadPass = checkFinalizerThread(finalizationEnabled); boolean calledPass = checkFinalizerCalled(finalizationEnabled); if (!threadPass || !calledPass) throw new AssertionError("Test failed."); } }