8276422: Add command-line option to disable finalization
Co-authored-by: David Holmes <dholmes@openjdk.org> Co-authored-by: Brent Christian <bchristi@openjdk.org> Reviewed-by: dholmes, kbarrett, bchristi
This commit is contained in:
parent
ec7cb6d5d3
commit
d7ad546758
@ -147,6 +147,7 @@ JVM_IsArrayClass
|
|||||||
JVM_IsCDSDumpingEnabled
|
JVM_IsCDSDumpingEnabled
|
||||||
JVM_IsConstructorIx
|
JVM_IsConstructorIx
|
||||||
JVM_IsDumpingClassList
|
JVM_IsDumpingClassList
|
||||||
|
JVM_IsFinalizationEnabled
|
||||||
JVM_IsHiddenClass
|
JVM_IsHiddenClass
|
||||||
JVM_IsInterface
|
JVM_IsInterface
|
||||||
JVM_IsPrimitiveClass
|
JVM_IsPrimitiveClass
|
||||||
|
@ -2835,7 +2835,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
|
|||||||
annotation_default_length,
|
annotation_default_length,
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
|
||||||
if (name == vmSymbols::finalize_method_name() &&
|
if (InstanceKlass::is_finalization_enabled() &&
|
||||||
|
name == vmSymbols::finalize_method_name() &&
|
||||||
signature == vmSymbols::void_method_signature()) {
|
signature == vmSymbols::void_method_signature()) {
|
||||||
if (m->is_empty_method()) {
|
if (m->is_empty_method()) {
|
||||||
_has_empty_finalizer = true;
|
_has_empty_finalizer = true;
|
||||||
@ -4171,7 +4172,8 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) {
|
|||||||
bool f = false;
|
bool f = false;
|
||||||
const Method* const m = ik->lookup_method(vmSymbols::finalize_method_name(),
|
const Method* const m = ik->lookup_method(vmSymbols::finalize_method_name(),
|
||||||
vmSymbols::void_method_signature());
|
vmSymbols::void_method_signature());
|
||||||
if (m != NULL && !m->is_empty_method()) {
|
if (InstanceKlass::is_finalization_enabled() &&
|
||||||
|
(m != NULL) && !m->is_empty_method()) {
|
||||||
f = true;
|
f = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,6 +759,9 @@ JVM_SupportsCX8(void);
|
|||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_ReportFinalizationComplete(JNIEnv *env, jobject finalizee);
|
JVM_ReportFinalizationComplete(JNIEnv *env, jobject finalizee);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
JVM_IsFinalizationEnabled(JNIEnv *env);
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
PART 2: Support for the Verifier and Class File Format Checker
|
PART 2: Support for the Verifier and Class File Format Checker
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
@ -141,6 +141,7 @@
|
|||||||
|
|
||||||
#endif // ndef DTRACE_ENABLED
|
#endif // ndef DTRACE_ENABLED
|
||||||
|
|
||||||
|
bool InstanceKlass::_finalization_enabled = true;
|
||||||
|
|
||||||
static inline bool is_class_loader(const Symbol* class_name,
|
static inline bool is_class_loader(const Symbol* class_name,
|
||||||
const ClassFileParser& parser) {
|
const ClassFileParser& parser) {
|
||||||
|
@ -329,7 +329,17 @@ class InstanceKlass: public Klass {
|
|||||||
|
|
||||||
static bool _disable_method_binary_search;
|
static bool _disable_method_binary_search;
|
||||||
|
|
||||||
|
// Controls finalizer registration
|
||||||
|
static bool _finalization_enabled;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Queries finalization state
|
||||||
|
static bool is_finalization_enabled() { return _finalization_enabled; }
|
||||||
|
|
||||||
|
// Sets finalization state
|
||||||
|
static void set_finalization_enabled(bool val) { _finalization_enabled = val; }
|
||||||
|
|
||||||
// The three BUILTIN class loader types
|
// The three BUILTIN class loader types
|
||||||
bool is_shared_boot_class() const {
|
bool is_shared_boot_class() const {
|
||||||
return (_misc_flags & _misc_is_shared_boot_class) != 0;
|
return (_misc_flags & _misc_is_shared_boot_class) != 0;
|
||||||
|
@ -690,6 +690,10 @@ JVM_ENTRY(void, JVM_ReportFinalizationComplete(JNIEnv * env, jobject finalizee))
|
|||||||
MANAGEMENT_ONLY(FinalizerService::on_complete(JNIHandles::resolve_non_null(finalizee), THREAD);)
|
MANAGEMENT_ONLY(FinalizerService::on_complete(JNIHandles::resolve_non_null(finalizee), THREAD);)
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(jboolean, JVM_IsFinalizationEnabled(JNIEnv * env))
|
||||||
|
return InstanceKlass::is_finalization_enabled();
|
||||||
|
JVM_END
|
||||||
|
|
||||||
// java.io.File ///////////////////////////////////////////////////////////////
|
// java.io.File ///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
JVM_LEAF(char*, JVM_NativePath(char* path))
|
JVM_LEAF(char*, JVM_NativePath(char* path))
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "logging/logStream.hpp"
|
#include "logging/logStream.hpp"
|
||||||
#include "logging/logTag.hpp"
|
#include "logging/logTag.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
@ -2887,6 +2888,17 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m
|
|||||||
if (FLAG_SET_CMDLINE(ErrorFileToStdout, true) != JVMFlag::SUCCESS) {
|
if (FLAG_SET_CMDLINE(ErrorFileToStdout, true) != JVMFlag::SUCCESS) {
|
||||||
return JNI_EINVAL;
|
return JNI_EINVAL;
|
||||||
}
|
}
|
||||||
|
} else if (match_option(option, "--finalization=", &tail)) {
|
||||||
|
if (strcmp(tail, "enabled") == 0) {
|
||||||
|
InstanceKlass::set_finalization_enabled(true);
|
||||||
|
} else if (strcmp(tail, "disabled") == 0) {
|
||||||
|
InstanceKlass::set_finalization_enabled(false);
|
||||||
|
} else {
|
||||||
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
|
"Invalid finalization value '%s', must be 'disabled' or 'enabled'.\n",
|
||||||
|
tail);
|
||||||
|
return JNI_EINVAL;
|
||||||
|
}
|
||||||
} else if (match_option(option, "-XX:+ExtendedDTraceProbes")) {
|
} else if (match_option(option, "-XX:+ExtendedDTraceProbes")) {
|
||||||
#if defined(DTRACE_ENABLED)
|
#if defined(DTRACE_ENABLED)
|
||||||
if (FLAG_SET_CMDLINE(ExtendedDTraceProbes, true) != JVMFlag::SUCCESS) {
|
if (FLAG_SET_CMDLINE(ExtendedDTraceProbes, true) != JVMFlag::SUCCESS) {
|
||||||
|
@ -61,9 +61,17 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
|
|||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final boolean ENABLED = isFinalizationEnabled();
|
||||||
|
|
||||||
|
private static native boolean isFinalizationEnabled();
|
||||||
|
|
||||||
/* Invoked by VM */
|
/* Invoked by VM */
|
||||||
static void register(Object finalizee) {
|
static void register(Object finalizee) {
|
||||||
new Finalizer(finalizee);
|
if (ENABLED) {
|
||||||
|
new Finalizer(finalizee);
|
||||||
|
} else {
|
||||||
|
throw new InternalError("unexpected call to Finalizer::register when finalization is disabled");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runFinalizer(JavaLangAccess jla) {
|
private void runFinalizer(JavaLangAccess jla) {
|
||||||
@ -130,7 +138,7 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
|
|||||||
|
|
||||||
/* Called by Runtime.runFinalization() */
|
/* Called by Runtime.runFinalization() */
|
||||||
static void runFinalization() {
|
static void runFinalization() {
|
||||||
if (VM.initLevel() == 0) {
|
if (VM.initLevel() == 0 || ! ENABLED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,14 +190,16 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
|
|||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
if (ENABLED) {
|
||||||
for (ThreadGroup tgn = tg;
|
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||||
tgn != null;
|
for (ThreadGroup tgn = tg;
|
||||||
tg = tgn, tgn = tg.getParent());
|
tgn != null;
|
||||||
Thread finalizer = new FinalizerThread(tg);
|
tg = tgn, tgn = tg.getParent());
|
||||||
finalizer.setPriority(Thread.MAX_PRIORITY - 2);
|
Thread finalizer = new FinalizerThread(tg);
|
||||||
finalizer.setDaemon(true);
|
finalizer.setPriority(Thread.MAX_PRIORITY - 2);
|
||||||
finalizer.start();
|
finalizer.setDaemon(true);
|
||||||
|
finalizer.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,10 @@ java.launcher.X.usage=\n\
|
|||||||
\ override or augment a module with classes and resources\n\
|
\ override or augment a module with classes and resources\n\
|
||||||
\ in JAR files or directories.\n\
|
\ in JAR files or directories.\n\
|
||||||
\ --source <version>\n\
|
\ --source <version>\n\
|
||||||
\ set the version of the source in source-file mode.\n\n\
|
\ set the version of the source in source-file mode.\n\
|
||||||
|
\ --finalization=<value>\n\
|
||||||
|
\ controls finalization\n\
|
||||||
|
\ <value> is one of "enabled" or "disabled"\n\n\
|
||||||
These extra options are subject to change without notice.\n
|
These extra options are subject to change without notice.\n
|
||||||
|
|
||||||
# Translators please note do not translate the options themselves
|
# Translators please note do not translate the options themselves
|
||||||
|
@ -32,4 +32,7 @@ Java_java_lang_ref_Finalizer_reportComplete(JNIEnv* env, jclass cls, jobject fin
|
|||||||
JVM_ReportFinalizationComplete(env, finalizee);
|
JVM_ReportFinalizationComplete(env, finalizee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_java_lang_ref_Finalizer_isFinalizationEnabled(JNIEnv* env, jclass cls) {
|
||||||
|
return JVM_IsFinalizationEnabled(env);
|
||||||
|
}
|
||||||
|
122
test/jdk/java/lang/Object/FinalizationOption.java
Normal file
122
test/jdk/java/lang/Object/FinalizationOption.java
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* 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.");
|
||||||
|
}
|
||||||
|
}
|
52
test/jdk/java/lang/Object/InvalidFinalizationOption.java
Normal file
52
test/jdk/java/lang/Object/InvalidFinalizationOption.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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 Invalid/missing values for the finalization option should be rejected
|
||||||
|
* @library /test/lib
|
||||||
|
* @run driver InvalidFinalizationOption
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.test.lib.process.ProcessTools;
|
||||||
|
import jdk.test.lib.process.OutputAnalyzer;
|
||||||
|
|
||||||
|
public class InvalidFinalizationOption {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
record TestData(String arg, String expected) { }
|
||||||
|
|
||||||
|
TestData[] testData = {
|
||||||
|
new TestData("--finalization", "Unrecognized option"),
|
||||||
|
new TestData("--finalization=", "Invalid finalization value"),
|
||||||
|
new TestData("--finalization=azerty", "Invalid finalization value")
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var data : testData) {
|
||||||
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(data.arg);
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain(data.expected);
|
||||||
|
output.shouldHaveExitValue(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,17 +34,20 @@ import jdk.test.lib.jfr.TestClassLoader;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
|
* @bug 8266936 8276422
|
||||||
* @summary The test verifies that classes overriding finalize() are represented as events.
|
* @summary The test verifies that classes overriding finalize() are represented as events.
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR
|
||||||
* @library /test/lib /test/jdk
|
* @library /test/lib /test/jdk
|
||||||
* @run main/othervm -Xlog:class+unload,finalizer -Xmx16m jdk.jfr.event.runtime.TestFinalizerStatisticsEvent
|
* @run main/othervm -Xlog:class+unload,finalizer -Xmx16m jdk.jfr.event.runtime.TestFinalizerStatisticsEvent
|
||||||
|
* @run main/othervm -Xlog:class+unload,finalizer -Xmx16m --finalization=disabled jdk.jfr.event.runtime.TestFinalizerStatisticsEvent disabled
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class TestFinalizerStatisticsEvent {
|
public final class TestFinalizerStatisticsEvent {
|
||||||
private final static String TEST_CLASS_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassOverridingFinalize";
|
private final static String TEST_CLASS_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassOverridingFinalize";
|
||||||
private final static String TEST_CLASS_UNLOAD_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassUnloadOverridingFinalize";
|
private final static String TEST_CLASS_UNLOAD_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassUnloadOverridingFinalize";
|
||||||
private final static String EVENT_PATH = EventNames.FinalizerStatistics;
|
private final static String EVENT_PATH = EventNames.FinalizerStatistics;
|
||||||
|
private static boolean disabled = false;
|
||||||
|
|
||||||
// Declare as public static to prevent the compiler from optimizing away all unread writes
|
// Declare as public static to prevent the compiler from optimizing away all unread writes
|
||||||
public static TestClassLoader unloadableClassLoader;
|
public static TestClassLoader unloadableClassLoader;
|
||||||
@ -52,6 +55,10 @@ public final class TestFinalizerStatisticsEvent {
|
|||||||
public static Object overridingInstance;
|
public static Object overridingInstance;
|
||||||
|
|
||||||
public static void main(String[] args) throws Throwable {
|
public static void main(String[] args) throws Throwable {
|
||||||
|
if (args.length > 0 && "disabled".equals(args[0])) {
|
||||||
|
disabled = true;
|
||||||
|
System.out.println("Testing with finalization disabled");
|
||||||
|
}
|
||||||
Recording recording1 = new Recording();
|
Recording recording1 = new Recording();
|
||||||
recording1.enable(EVENT_PATH);
|
recording1.enable(EVENT_PATH);
|
||||||
Recording recording2 = new Recording();
|
Recording recording2 = new Recording();
|
||||||
@ -69,8 +76,12 @@ public final class TestFinalizerStatisticsEvent {
|
|||||||
recording1.stop(); // rotation writes an event for TEST_CLASS_NAME into recording1 which now has 4 events reflecting this test case (3 chunks + 1 unload)
|
recording1.stop(); // rotation writes an event for TEST_CLASS_NAME into recording1 which now has 4 events reflecting this test case (3 chunks + 1 unload)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
verify(recording2);
|
if (disabled) {
|
||||||
verify(recording1);
|
verifyDisabled(recording1);
|
||||||
|
} else {
|
||||||
|
verifyEnabled(recording2);
|
||||||
|
verifyEnabled(recording1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
recording2.close();
|
recording2.close();
|
||||||
@ -84,7 +95,8 @@ public final class TestFinalizerStatisticsEvent {
|
|||||||
System.gc();
|
System.gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void verify(Recording recording) throws Throwable {
|
/* Verify correct operation with finalization enabled */
|
||||||
|
private static void verifyEnabled(Recording recording) throws Throwable {
|
||||||
boolean foundTestClassName = false;
|
boolean foundTestClassName = false;
|
||||||
boolean foundTestClassUnloadName = false;
|
boolean foundTestClassUnloadName = false;
|
||||||
List<RecordedEvent> events = Events.fromRecording(recording);
|
List<RecordedEvent> events = Events.fromRecording(recording);
|
||||||
@ -108,6 +120,19 @@ public final class TestFinalizerStatisticsEvent {
|
|||||||
Asserts.assertTrue(foundTestClassUnloadName, "The class: " + TEST_CLASS_UNLOAD_NAME + " overriding finalize() is not found");
|
Asserts.assertTrue(foundTestClassUnloadName, "The class: " + TEST_CLASS_UNLOAD_NAME + " overriding finalize() is not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify no jdk.FinalizerStatistics events with finalization disabled */
|
||||||
|
private static void verifyDisabled(Recording recording) throws Throwable {
|
||||||
|
int f10nEvents = 0;
|
||||||
|
List<RecordedEvent> events = Events.fromRecording(recording);
|
||||||
|
for (RecordedEvent event : events) {
|
||||||
|
System.out.println("Event:" + event);
|
||||||
|
if ("jdk.FinalizerStatistics".equals(event.getEventType().getName())) {
|
||||||
|
f10nEvents++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Asserts.assertEquals(f10nEvents, 0, "Finalization disabled, but recorded " + f10nEvents + " jdk.FinalizerStatistics events");
|
||||||
|
}
|
||||||
|
|
||||||
static public class TestClassOverridingFinalize {
|
static public class TestClassOverridingFinalize {
|
||||||
public boolean finalized = false;
|
public boolean finalized = false;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user