--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -186,10 +186,7 @@
// GC root of class loader data created.
ClassLoaderData* volatile ClassLoaderDataGraph::_head = NULL;
ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL;
-ClassLoaderData* ClassLoaderDataGraph::_saved_unloading = NULL;
-ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL;
-bool ClassLoaderDataGraph::_should_purge = false;
bool ClassLoaderDataGraph::_should_clean_deallocate_lists = false;
bool ClassLoaderDataGraph::_safepoint_cleanup_needed = false;
bool ClassLoaderDataGraph::_metaspace_oom = false;
@@ -249,9 +246,7 @@
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
- // Only walk the head until any clds not purged from prior unloading
- // (CMS doesn't purge right away).
- for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+ for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cl->do_cld(cld);
}
@@ -381,9 +376,7 @@
void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
- // Only walk the head until any clds not purged from prior unloading
- // (CMS doesn't purge right away).
- for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+ for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->modules_do(f);
}
@@ -399,9 +392,7 @@
void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
- // Only walk the head until any clds not purged from prior unloading
- // (CMS doesn't purge right away).
- for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+ for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->packages_do(f);
}
@@ -424,9 +415,7 @@
void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
- // Only walk the head until any clds not purged from prior unloading
- // (CMS doesn't purge right away).
- for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+ for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->classes_do(f);
}
@@ -476,32 +465,6 @@
}
}
-GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
- assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
- assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
-
- GrowableArray<ClassLoaderData*>* array = new GrowableArray<ClassLoaderData*>();
-
- // The CLDs in [_head, _saved_head] were all added during last call to remember_new_clds(true);
- ClassLoaderData* curr = _head;
- while (curr != _saved_head) {
- if (!curr->claimed(ClassLoaderData::_claim_strong)) {
- array->push(curr);
- LogTarget(Debug, class, loader, data) lt;
- if (lt.is_enabled()) {
- LogStream ls(lt);
- ls.print("found new CLD: ");
- curr->print_value_on(&ls);
- ls.cr();
- }
- }
-
- curr = curr->_next;
- }
-
- return array;
-}
-
#ifndef PRODUCT
bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
@@ -544,10 +507,6 @@
uint loaders_processed = 0;
uint loaders_removed = 0;
- // Save previous _unloading pointer for CMS which may add to unloading list before
- // purging and we don't want to rewalk the previously unloaded class loader data.
- _saved_unloading = _unloading;
-
data = _head;
while (data != NULL) {
if (data->is_alive()) {
--- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp Tue Nov 26 10:22:13 2019 +0000
@@ -43,10 +43,6 @@
// All CLDs (except the null CLD) can be reached by walking _head->_next->...
static ClassLoaderData* volatile _head;
static ClassLoaderData* _unloading;
- // CMS support.
- static ClassLoaderData* _saved_head;
- static ClassLoaderData* _saved_unloading;
- static bool _should_purge;
// Set if there's anything to purge in the deallocate lists or previous versions
// during a safepoint after class unloading in a full GC.
@@ -115,18 +111,6 @@
static void print_dictionary(outputStream* st);
static void print_table_statistics(outputStream* st);
- // CMS support.
- static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
- static GrowableArray<ClassLoaderData*>* new_clds();
-
- static void set_should_purge(bool b) { _should_purge = b; }
- static bool should_purge_and_reset() {
- bool res = _should_purge;
- // reset for next time.
- set_should_purge(false);
- return res;
- }
-
static int resize_dictionaries();
static bool has_metaspace_oom() { return _metaspace_oom; }
--- a/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -32,7 +32,9 @@
#include "jfr/support/jfrEventClass.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
+#include "prims/jvmtiEnvBase.hpp"
#include "prims/jvmtiExport.hpp"
+#include "prims/jvmtiUtil.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp"
@@ -52,19 +54,17 @@
}
}
-static jvmtiError set_event_notification_mode(jvmtiEventMode mode,
- jvmtiEvent event,
- jthread event_thread,
- ...) {
- if (jfr_jvmti_env == NULL) {
- return JVMTI_ERROR_NONE;
- }
+static bool set_event_notification_mode(jvmtiEventMode mode,
+ jvmtiEvent event,
+ jthread event_thread,
+ ...) {
+ assert(jfr_jvmti_env != NULL, "invariant");
const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventNotificationMode(mode, event, event_thread);
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventNotificationMode");
- return jvmti_ret_code;
+ return jvmti_ret_code == JVMTI_ERROR_NONE;
}
-static jvmtiError update_class_file_load_hook_event(jvmtiEventMode mode) {
+static bool update_class_file_load_hook_event(jvmtiEventMode mode) {
return set_event_notification_mode(mode, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
}
@@ -117,12 +117,23 @@
return classes;
}
-static void log_and_throw(TRAPS) {
+// caller needs ResourceMark
+static void log_and_throw(jvmtiError error, TRAPS) {
if (!HAS_PENDING_EXCEPTION) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
- log_error(jfr, system)("JfrJvmtiAgent::retransformClasses failed");
- JfrJavaSupport::throw_class_format_error("JfrJvmtiAgent::retransformClasses failed", THREAD);
+ const char base_error_msg[] = "JfrJvmtiAgent::retransformClasses failed: ";
+ size_t length = sizeof base_error_msg; // includes terminating null
+ const char* const jvmti_error_name = JvmtiUtil::error_name(error);
+ assert(jvmti_error_name != NULL, "invariant");
+ length += strlen(jvmti_error_name);
+ char* error_msg = NEW_RESOURCE_ARRAY(char, length);
+ jio_snprintf(error_msg, length, "%s%s", base_error_msg, jvmti_error_name);
+ if (JVMTI_ERROR_INVALID_CLASS_FORMAT == error) {
+ JfrJavaSupport::throw_class_format_error(error_msg, THREAD);
+ } else {
+ JfrJavaSupport::throw_runtime_exception(error_msg, THREAD);
+ }
}
}
@@ -137,12 +148,15 @@
}
}
+static bool is_valid_jvmti_phase() {
+ return JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE;
+}
+
void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, TRAPS) {
assert(env != NULL, "invariant");
+ assert(classes_array != NULL, "invariant");
+ assert(is_valid_jvmti_phase(), "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
- if (classes_array == NULL) {
- return;
- }
const jint classes_count = env->GetArrayLength(classes_array);
if (classes_count <= 0) {
return;
@@ -153,27 +167,27 @@
for (jint i = 0; i < classes_count; i++) {
jclass clz = (jclass)env->GetObjectArrayElement(classes_array, i);
check_exception_and_log(env, THREAD);
-
+ classes[i] = clz;
+ }
+ {
// inspecting the oop/klass requires a thread transition
- {
- ThreadInVMfromNative transition((JavaThread*)THREAD);
- if (JdkJfrEvent::is_a(clz)) {
- // should have been tagged already
- assert(JdkJfrEvent::is_subklass(clz), "invariant");
- } else {
+ ThreadInVMfromNative transition((JavaThread*)THREAD);
+ for (jint i = 0; i < classes_count; ++i) {
+ jclass clz = classes[i];
+ if (!JdkJfrEvent::is_a(clz)) {
// outside the event hierarchy
JdkJfrEvent::tag_as_host(clz);
}
}
-
- classes[i] = clz;
}
- if (jfr_jvmti_env->RetransformClasses(classes_count, classes) != JVMTI_ERROR_NONE) {
- log_and_throw(THREAD);
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
+ const jvmtiError result = jfr_jvmti_env->RetransformClasses(classes_count, classes);
+ if (result != JVMTI_ERROR_NONE) {
+ log_and_throw(result, THREAD);
}
}
-static jvmtiError register_callbacks(JavaThread* jt) {
+static bool register_callbacks(JavaThread* jt) {
assert(jfr_jvmti_env != NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
jvmtiEventCallbacks callbacks;
@@ -182,10 +196,10 @@
callbacks.ClassFileLoadHook = jfr_on_class_file_load_hook;
const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
- return jvmti_ret_code;
+ return jvmti_ret_code == JVMTI_ERROR_NONE;
}
-static jvmtiError register_capabilities(JavaThread* jt) {
+static bool register_capabilities(JavaThread* jt) {
assert(jfr_jvmti_env != NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
jvmtiCapabilities capabilities;
@@ -195,7 +209,7 @@
capabilities.can_retransform_any_class = 1;
const jvmtiError jvmti_ret_code = jfr_jvmti_env->AddCapabilities(&capabilities);
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "Add Capabilities");
- return jvmti_ret_code;
+ return jvmti_ret_code == JVMTI_ERROR_NONE;
}
static jint create_jvmti_env(JavaThread* jt) {
@@ -206,16 +220,14 @@
return vm->GetEnv((void **)&jfr_jvmti_env, JVMTI_VERSION);
}
-static jvmtiError unregister_callbacks(JavaThread* jt) {
- if (jfr_jvmti_env == NULL) {
- return JVMTI_ERROR_NONE;
- }
+static bool unregister_callbacks(JavaThread* jt) {
+ assert(jfr_jvmti_env != NULL, "invariant");
jvmtiEventCallbacks callbacks;
/* Set empty callbacks */
memset(&callbacks, 0, sizeof(callbacks));
const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
- return jvmti_ret_code;
+ return jvmti_ret_code == JVMTI_ERROR_NONE;
}
JfrJvmtiAgent::JfrJvmtiAgent() {}
@@ -223,20 +235,17 @@
JfrJvmtiAgent::~JfrJvmtiAgent() {
JavaThread* jt = current_java_thread();
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
- ThreadToNativeFromVM transition(jt);
- update_class_file_load_hook_event(JVMTI_DISABLE);
- unregister_callbacks(jt);
if (jfr_jvmti_env != NULL) {
+ ThreadToNativeFromVM transition(jt);
+ update_class_file_load_hook_event(JVMTI_DISABLE);
+ unregister_callbacks(jt);
jfr_jvmti_env->DisposeEnvironment();
jfr_jvmti_env = NULL;
}
- agent = NULL;
}
-static bool initialize() {
- JavaThread* const jt = current_java_thread();
+static bool initialize(JavaThread* jt) {
assert(jt != NULL, "invariant");
- assert(jt->thread_state() == _thread_in_vm, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
ThreadToNativeFromVM transition(jt);
if (create_jvmti_env(jt) != JNI_OK) {
@@ -244,25 +253,36 @@
return false;
}
assert(jfr_jvmti_env != NULL, "invariant");
- if (register_capabilities(jt) != JVMTI_ERROR_NONE) {
+ if (!register_capabilities(jt)) {
+ return false;
+ }
+ if (!register_callbacks(jt)) {
return false;
}
- if (register_callbacks(jt) != JVMTI_ERROR_NONE) {
- return false;
- }
- if (update_class_file_load_hook_event(JVMTI_ENABLE) != JVMTI_ERROR_NONE) {
- return false;
- }
- return true;
+ return update_class_file_load_hook_event(JVMTI_ENABLE);
+}
+
+static void log_and_throw_illegal_state_exception(TRAPS) {
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
+ const char* const illegal_state_msg = "An attempt was made to start JFR too early in the VM initialization sequence.";
+ log_error(jfr, system)(illegal_state_msg);
+ log_error(jfr, system)("JFR uses JVMTI RetransformClasses and requires the JVMTI state to have entered JVMTI_PHASE_LIVE.");
+ log_error(jfr, system)("Please initialize JFR in response to event JVMTI_EVENT_VM_INIT instead of JVMTI_EVENT_VM_START.");
+ JfrJavaSupport::throw_illegal_state_exception(illegal_state_msg, THREAD);
}
bool JfrJvmtiAgent::create() {
- assert(jfr_jvmti_env == NULL, "invariant");
+ assert(agent == NULL, "invariant");
+ JavaThread* const jt = current_java_thread();
+ if (!is_valid_jvmti_phase()) {
+ log_and_throw_illegal_state_exception(jt);
+ return false;
+ }
agent = new JfrJvmtiAgent();
if (agent == NULL) {
return false;
}
- if (!initialize()) {
+ if (!initialize(jt)) {
delete agent;
agent = NULL;
return false;
@@ -276,4 +296,3 @@
agent = NULL;
}
}
-
--- a/src/hotspot/share/jfr/jfr.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/jfr.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -45,15 +45,21 @@
return JfrRecorder::is_recording();
}
-void Jfr::on_vm_init() {
- if (!JfrRecorder::on_vm_init()) {
- vm_exit_during_initialization("Failure when starting JFR on_vm_init");
+void Jfr::on_create_vm_1() {
+ if (!JfrRecorder::on_create_vm_1()) {
+ vm_exit_during_initialization("Failure when starting JFR on_create_vm_1");
}
}
-void Jfr::on_vm_start() {
- if (!JfrRecorder::on_vm_start()) {
- vm_exit_during_initialization("Failure when starting JFR on_vm_start");
+void Jfr::on_create_vm_2() {
+ if (!JfrRecorder::on_create_vm_2()) {
+ vm_exit_during_initialization("Failure when starting JFR on_create_vm_2");
+ }
+}
+
+void Jfr::on_create_vm_3() {
+ if (!JfrRecorder::on_create_vm_3()) {
+ vm_exit_during_initialization("Failure when starting JFR on_create_vm_3");
}
}
--- a/src/hotspot/share/jfr/jfr.hpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/jfr.hpp Tue Nov 26 10:22:13 2019 +0000
@@ -43,8 +43,9 @@
static bool is_enabled();
static bool is_disabled();
static bool is_recording();
- static void on_vm_init();
- static void on_vm_start();
+ static void on_create_vm_1();
+ static void on_create_vm_2();
+ static void on_create_vm_3();
static void on_unloading_classes();
static void on_thread_start(Thread* thread);
static void on_thread_exit(Thread* thread);
--- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -540,6 +540,10 @@
create_and_throw(vmSymbols::java_lang_ClassFormatError(), message, THREAD);
}
+void JfrJavaSupport::throw_runtime_exception(const char* message, TRAPS) {
+ create_and_throw(vmSymbols::java_lang_RuntimeException(), message, THREAD);
+}
+
void JfrJavaSupport::abort(jstring errorMsg, Thread* t) {
DEBUG_ONLY(check_java_thread_in_vm(t));
--- a/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp Tue Nov 26 10:22:13 2019 +0000
@@ -84,6 +84,7 @@
static void throw_internal_error(const char* message, TRAPS);
static void throw_out_of_memory_error(const char* message, TRAPS);
static void throw_class_format_error(const char* message, TRAPS);
+ static void throw_runtime_exception(const char* message, TRAPS);
static bool is_jdk_jfr_module_available();
static bool is_jdk_jfr_module_available(outputStream* stream, TRAPS);
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -192,7 +192,9 @@
return JNI_TRUE;
}
if (!JfrRecorder::create(simulate_failure == JNI_TRUE)) {
- JfrJavaSupport::throw_illegal_state_exception("Unable to start Jfr", thread);
+ if (!thread->has_pending_exception()) {
+ JfrJavaSupport::throw_illegal_state_exception("Unable to start Jfr", thread);
+ }
return JNI_FALSE;
}
return JNI_TRUE;
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -461,7 +461,6 @@
}
size_t JfrCheckpointManager::flush_type_set() {
- assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
size_t elements = 0;
{
JfrCheckpointWriter writer(Thread::current());
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -46,6 +46,9 @@
#include "runtime/handles.inline.hpp"
#include "runtime/globals_extension.hpp"
#include "utilities/growableArray.hpp"
+#ifdef ASSERT
+#include "prims/jvmtiEnvBase.hpp"
+#endif
bool JfrRecorder::is_disabled() {
// True if -XX:-FlightRecorder has been explicitly set on the
@@ -57,7 +60,9 @@
static bool enable() {
assert(!_enabled, "invariant");
- FLAG_SET_MGMT(FlightRecorder, true);
+ if (!FlightRecorder) {
+ FLAG_SET_MGMT(FlightRecorder, true);
+ }
_enabled = FlightRecorder;
assert(_enabled, "invariant");
return _enabled;
@@ -67,7 +72,7 @@
return _enabled;
}
-bool JfrRecorder::on_vm_init() {
+bool JfrRecorder::on_create_vm_1() {
if (!is_disabled()) {
if (FlightRecorder || StartFlightRecording != NULL) {
enable();
@@ -92,7 +97,7 @@
static void teardown_startup_support() {
release_recordings();
- JfrOptionSet::release_startup_recording_options();
+ JfrOptionSet::release_start_flight_recording_options();
}
// Parsing options here to detect errors as soon as possible
@@ -110,7 +115,7 @@
}
static bool validate_recording_options(TRAPS) {
- const GrowableArray<const char*>* options = JfrOptionSet::startup_recording_options();
+ const GrowableArray<const char*>* options = JfrOptionSet::start_flight_recording_options();
if (options == NULL) {
return true;
}
@@ -143,7 +148,7 @@
return true;
}
-static bool launch_recordings(TRAPS) {
+static bool launch_command_line_recordings(TRAPS) {
bool result = true;
if (dcmd_recordings_array != NULL) {
const int length = dcmd_recordings_array->length();
@@ -168,7 +173,7 @@
static bool is_cds_dump_requested() {
// we will not be able to launch recordings if a cds dump is being requested
- if (Arguments::is_dumping_archive() && (JfrOptionSet::startup_recording_options() != NULL)) {
+ if (Arguments::is_dumping_archive() && (JfrOptionSet::start_flight_recording_options() != NULL)) {
warning("JFR will be disabled during CDS dumping");
teardown_startup_support();
return true;
@@ -176,7 +181,7 @@
return false;
}
-bool JfrRecorder::on_vm_start() {
+bool JfrRecorder::on_create_vm_2() {
if (is_cds_dump_requested()) {
return true;
}
@@ -187,9 +192,7 @@
if (!register_jfr_dcmds()) {
return false;
}
-
const bool in_graph = JfrJavaSupport::is_jdk_jfr_module_available();
-
if (in_graph) {
if (!validate_recording_options(thread)) {
return false;
@@ -198,17 +201,19 @@
return false;
}
}
-
if (!is_enabled()) {
return true;
}
-
if (!in_graph) {
log_jdk_jfr_module_resolution_error(thread);
return false;
}
+ return true;
+}
- return launch_recordings(thread);
+bool JfrRecorder::on_create_vm_3() {
+ assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE, "invalid init sequence");
+ return launch_command_line_recordings(Thread::current());
}
static bool _created = false;
@@ -277,7 +282,6 @@
}
// subsystems
-static JfrJvmtiAgent* _jvmti_agent = NULL;
static JfrPostBox* _post_box = NULL;
static JfrStorage* _storage = NULL;
static JfrCheckpointManager* _checkpoint_manager = NULL;
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp Tue Nov 26 10:22:13 2019 +0000
@@ -38,6 +38,9 @@
friend class Jfr;
friend void recorderthread_entry(JavaThread*, Thread*);
private:
+ static bool on_create_vm_1();
+ static bool on_create_vm_2();
+ static bool on_create_vm_3();
static bool create_checkpoint_manager();
static bool create_chunk_repository();
static bool create_java_event_writer();
@@ -52,8 +55,6 @@
static bool create_components();
static void destroy_components();
static void on_recorder_thread_exit();
- static bool on_vm_start();
- static bool on_vm_init();
public:
static bool is_enabled();
--- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -677,7 +677,7 @@
return false;
}
-static GrowableArray<const char*>* startup_recording_options_array = NULL;
+static GrowableArray<const char*>* start_flight_recording_options_array = NULL;
bool JfrOptionSet::parse_start_flight_recording_option(const JavaVMOption** option, char* delimiter) {
assert(option != NULL, "invariant");
@@ -700,28 +700,28 @@
assert(value != NULL, "invariant");
const size_t value_length = strlen(value);
- if (startup_recording_options_array == NULL) {
- startup_recording_options_array = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<const char*>(8, true, mtTracing);
+ if (start_flight_recording_options_array == NULL) {
+ start_flight_recording_options_array = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<const char*>(8, true, mtTracing);
}
- assert(startup_recording_options_array != NULL, "invariant");
+ assert(start_flight_recording_options_array != NULL, "invariant");
char* const startup_value = NEW_C_HEAP_ARRAY(char, value_length + 1, mtTracing);
strncpy(startup_value, value, value_length + 1);
assert(strncmp(startup_value, value, value_length) == 0, "invariant");
- startup_recording_options_array->append(startup_value);
+ start_flight_recording_options_array->append(startup_value);
return false;
}
-const GrowableArray<const char*>* JfrOptionSet::startup_recording_options() {
- return startup_recording_options_array;
+const GrowableArray<const char*>* JfrOptionSet::start_flight_recording_options() {
+ return start_flight_recording_options_array;
}
-void JfrOptionSet::release_startup_recording_options() {
- if (startup_recording_options_array != NULL) {
- const int length = startup_recording_options_array->length();
+void JfrOptionSet::release_start_flight_recording_options() {
+ if (start_flight_recording_options_array != NULL) {
+ const int length = start_flight_recording_options_array->length();
for (int i = 0; i < length; ++i) {
- FREE_C_HEAP_ARRAY(char, startup_recording_options_array->at(i));
+ FREE_C_HEAP_ARRAY(char, start_flight_recording_options_array->at(i));
}
- delete startup_recording_options_array;
- startup_recording_options_array = NULL;
+ delete start_flight_recording_options_array;
+ start_flight_recording_options_array = NULL;
}
}
--- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp Tue Nov 26 10:22:13 2019 +0000
@@ -80,8 +80,8 @@
static bool parse_flight_recorder_option(const JavaVMOption** option, char* delimiter);
static bool parse_start_flight_recording_option(const JavaVMOption** option, char* delimiter);
- static const GrowableArray<const char*>* startup_recording_options();
- static void release_startup_recording_options();
+ static const GrowableArray<const char*>* start_flight_recording_options();
+ static void release_start_flight_recording_options();
};
#endif // SHARE_JFR_RECORDER_SERVICE_JFROPTIONSET_HPP
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -702,7 +702,7 @@
}
void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
- oop nmethod_mirror = get_nmethod_mirror(nm, /* phantom_ref */ true);
+ oop nmethod_mirror = get_nmethod_mirror(nm, /* phantom_ref */ false);
if (nmethod_mirror == NULL) {
return;
}
--- a/src/hotspot/share/runtime/safepoint.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/runtime/safepoint.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -620,19 +620,6 @@
}
}
- if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_CLD_PURGE)) {
- if (ClassLoaderDataGraph::should_purge_and_reset()) {
- // CMS delays purging the CLDG until the beginning of the next safepoint and to
- // make sure concurrent sweep is done
- const char* name = "purging class loader data graph";
- EventSafepointCleanupTask event;
- TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
- ClassLoaderDataGraph::purge();
-
- post_safepoint_cleanup_task_event(event, safepoint_id, name);
- }
- }
-
if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_SYSTEM_DICTIONARY_RESIZE)) {
if (Dictionary::does_any_dictionary_needs_resizing()) {
const char* name = "resizing system dictionaries";
--- a/src/hotspot/share/runtime/safepoint.hpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/runtime/safepoint.hpp Tue Nov 26 10:22:13 2019 +0000
@@ -75,7 +75,6 @@
SAFEPOINT_CLEANUP_COMPILATION_POLICY,
SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH,
SAFEPOINT_CLEANUP_STRING_TABLE_REHASH,
- SAFEPOINT_CLEANUP_CLD_PURGE,
SAFEPOINT_CLEANUP_SYSTEM_DICTIONARY_RESIZE,
SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP,
// Leave this one last.
--- a/src/hotspot/share/runtime/thread.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/src/hotspot/share/runtime/thread.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -3887,7 +3887,7 @@
return status;
}
- JFR_ONLY(Jfr::on_vm_init();)
+ JFR_ONLY(Jfr::on_create_vm_1();)
// Should be done after the heap is fully created
main_thread->cache_global_variables();
@@ -4026,6 +4026,8 @@
// loaded until phase 2 completes
call_initPhase2(CHECK_JNI_ERR);
+ JFR_ONLY(Jfr::on_create_vm_2();)
+
// Always call even when there are not JVMTI environments yet, since environments
// may be attached late and JVMTI must track phases of VM execution
JvmtiExport::enter_start_phase();
@@ -4061,7 +4063,7 @@
// Notify JVMTI agents that VM initialization is complete - nop if no agents.
JvmtiExport::post_vm_initialized();
- JFR_ONLY(Jfr::on_vm_start();)
+ JFR_ONLY(Jfr::on_create_vm_3();)
#if INCLUDE_MANAGEMENT
Management::initialize(THREAD);
--- a/src/java.base/share/classes/java/io/File.java Mon Nov 25 15:16:29 2019 +0000
+++ b/src/java.base/share/classes/java/io/File.java Tue Nov 26 10:22:13 2019 +0000
@@ -29,6 +29,7 @@
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
+import java.nio.file.FileStore;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.security.SecureRandom;
@@ -1798,10 +1799,13 @@
/**
* Returns the size of the partition <a href="#partName">named</a> by this
- * abstract pathname.
+ * abstract pathname. If the total number of bytes in the partition is
+ * greater than {@link Long#MAX_VALUE}, then {@code Long.MAX_VALUE} will be
+ * returned.
*
* @return The size, in bytes, of the partition or {@code 0L} if this
- * abstract pathname does not name a partition
+ * abstract pathname does not name a partition or if the size
+ * cannot be obtained
*
* @throws SecurityException
* If a security manager has been installed and it denies
@@ -1810,6 +1814,7 @@
* read access to the file named by this abstract pathname
*
* @since 1.6
+ * @see FileStore#getTotalSpace
*/
public long getTotalSpace() {
SecurityManager sm = System.getSecurityManager();
@@ -1820,12 +1825,15 @@
if (isInvalid()) {
return 0L;
}
- return fs.getSpace(this, FileSystem.SPACE_TOTAL);
+ long space = fs.getSpace(this, FileSystem.SPACE_TOTAL);
+ return space >= 0L ? space : Long.MAX_VALUE;
}
/**
* Returns the number of unallocated bytes in the partition <a
- * href="#partName">named</a> by this abstract path name.
+ * href="#partName">named</a> by this abstract path name. If the
+ * number of unallocated bytes in the partition is greater than
+ * {@link Long#MAX_VALUE}, then {@code Long.MAX_VALUE} will be returned.
*
* <p> The returned number of unallocated bytes is a hint, but not
* a guarantee, that it is possible to use most or any of these
@@ -1837,9 +1845,10 @@
* will succeed.
*
* @return The number of unallocated bytes on the partition or {@code 0L}
- * if the abstract pathname does not name a partition. This
- * value will be less than or equal to the total file system size
- * returned by {@link #getTotalSpace}.
+ * if the abstract pathname does not name a partition or if this
+ * number cannot be obtained. This value will be less than or
+ * equal to the total file system size returned by
+ * {@link #getTotalSpace}.
*
* @throws SecurityException
* If a security manager has been installed and it denies
@@ -1848,6 +1857,7 @@
* read access to the file named by this abstract pathname
*
* @since 1.6
+ * @see FileStore#getUnallocatedSpace
*/
public long getFreeSpace() {
SecurityManager sm = System.getSecurityManager();
@@ -1858,16 +1868,19 @@
if (isInvalid()) {
return 0L;
}
- return fs.getSpace(this, FileSystem.SPACE_FREE);
+ long space = fs.getSpace(this, FileSystem.SPACE_FREE);
+ return space >= 0L ? space : Long.MAX_VALUE;
}
/**
* Returns the number of bytes available to this virtual machine on the
- * partition <a href="#partName">named</a> by this abstract pathname. When
- * possible, this method checks for write permissions and other operating
- * system restrictions and will therefore usually provide a more accurate
- * estimate of how much new data can actually be written than {@link
- * #getFreeSpace}.
+ * partition <a href="#partName">named</a> by this abstract pathname. If
+ * the number of available bytes in the partition is greater than
+ * {@link Long#MAX_VALUE}, then {@code Long.MAX_VALUE} will be returned.
+ * When possible, this method checks for write permissions and other
+ * operating system restrictions and will therefore usually provide a more
+ * accurate estimate of how much new data can actually be written than
+ * {@link #getFreeSpace}.
*
* <p> The returned number of available bytes is a hint, but not a
* guarantee, that it is possible to use most or any of these bytes. The
@@ -1878,9 +1891,10 @@
* to this file system will succeed.
*
* @return The number of available bytes on the partition or {@code 0L}
- * if the abstract pathname does not name a partition. On
- * systems where this information is not available, this method
- * will be equivalent to a call to {@link #getFreeSpace}.
+ * if the abstract pathname does not name a partition or if this
+ * number cannot be obtained. On systems where this information
+ * is not available, this method will be equivalent to a call to
+ * {@link #getFreeSpace}.
*
* @throws SecurityException
* If a security manager has been installed and it denies
@@ -1889,6 +1903,7 @@
* read access to the file named by this abstract pathname
*
* @since 1.6
+ * @see FileStore#getUsableSpace
*/
public long getUsableSpace() {
SecurityManager sm = System.getSecurityManager();
@@ -1899,7 +1914,8 @@
if (isInvalid()) {
return 0L;
}
- return fs.getSpace(this, FileSystem.SPACE_USABLE);
+ long space = fs.getSpace(this, FileSystem.SPACE_USABLE);
+ return space >= 0L ? space : Long.MAX_VALUE;
}
/* -- Temporary files -- */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Mon Nov 25 15:16:29 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Nov 26 10:22:13 2019 +0000
@@ -2266,8 +2266,7 @@
boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage() {
return ((tree.sym.flags() & PROTECTED) != 0 &&
- tree.sym.packge() != owner.packge() &&
- !owner.enclClass().isSubClass(tree.sym.owner, types));
+ tree.sym.packge() != owner.packge());
}
/**
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java Mon Nov 25 15:16:29 2019 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java Tue Nov 26 10:22:13 2019 +0000
@@ -37,7 +37,6 @@
import java.util.Set;
import jdk.internal.misc.VM;
-import jdk.internal.reflect.Reflection;
/**
* Provides utilities needed by JVMCI clients.
@@ -136,29 +135,6 @@
}
}
- private static boolean jvmciEnabled = true;
-
- /**
- * When {@code -XX:-UseJVMCIClassLoader} is in use, JVMCI classes are loaded via the boot class
- * loader. When {@code null} is the second argument to
- * {@link ServiceLoader#load(Class, ClassLoader)}, service lookup will use the system class
- * loader and thus find application classes which violates the API of {@link #load} and
- * {@link #loadSingle}. To avoid this, a class loader that simply delegates to the boot class
- * loader is used.
- */
- static class LazyBootClassPath {
- static final ClassLoader bootClassPath = new ClassLoader(null) {
- };
- }
-
- private static ClassLoader findBootClassLoaderChild(ClassLoader start) {
- ClassLoader cl = start;
- while (cl.getParent() != null) {
- cl = cl.getParent();
- }
- return cl;
- }
-
private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
@SuppressWarnings("unchecked")
@@ -173,33 +149,7 @@
}
}
- Iterable<S> providers = Collections.emptyList();
- if (jvmciEnabled) {
- ClassLoader cl = null;
- try {
- cl = getJVMCIClassLoader();
- if (cl == null) {
- cl = LazyBootClassPath.bootClassPath;
- // JVMCI classes are loaded via the boot class loader.
- // If we use null as the second argument to ServiceLoader.load,
- // service loading will use the system class loader
- // and find classes on the application class path. Since we
- // don't want this, we use a loader that is as close to the
- // boot class loader as possible (since it is impossible
- // to force service loading to use only the boot class loader).
- cl = findBootClassLoaderChild(ClassLoader.getSystemClassLoader());
- }
- providers = ServiceLoader.load(service, cl);
- } catch (UnsatisfiedLinkError e) {
- jvmciEnabled = false;
- } catch (InternalError e) {
- if (e.getMessage().equals("JVMCI is not enabled")) {
- jvmciEnabled = false;
- } else {
- throw e;
- }
- }
- }
+ Iterable<S> providers = ServiceLoader.load(service, ClassLoader.getSystemClassLoader());
if (IS_BUILDING_NATIVE_IMAGE) {
synchronized (servicesCache) {
ArrayList<S> providersList = new ArrayList<>();
@@ -278,23 +228,6 @@
return singleProvider;
}
- static {
- Reflection.registerMethodsToFilter(Services.class, Set.of("getJVMCIClassLoader"));
- }
-
- /**
- * Gets the JVMCI class loader.
- *
- * @throws InternalError with the {@linkplain Throwable#getMessage() message}
- * {@code "JVMCI is not enabled"} iff JVMCI is not enabled
- */
- private static ClassLoader getJVMCIClassLoader() {
- if (IS_IN_NATIVE_IMAGE) {
- return null;
- }
- return ClassLoader.getSystemClassLoader();
- }
-
/**
* A Java {@code char} has a maximal UTF8 length of 3.
*/
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Mon Nov 25 15:16:29 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Tue Nov 26 10:22:13 2019 +0000
@@ -203,6 +203,8 @@
* Call to invoke event tagging and retransformation of the passed classes
*
* @param classes
+ *
+ * @throws IllegalStateException if wrong JVMTI phase.
*/
public native synchronized void retransformClasses(Class<?>[] classes);
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java Mon Nov 25 15:16:29 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java Tue Nov 26 10:22:13 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -123,6 +123,8 @@
list.add(java.lang.Error.class);
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Retransformed JDK classes");
jvm.retransformClasses(list.toArray(new Class<?>[list.size()]));
+ } catch (IllegalStateException ise) {
+ throw ise;
} catch (Exception e) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not add instrumentation for JDK events. " + e.getMessage());
}
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat001/thrstat001.cpp Mon Nov 25 15:16:29 2019 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat001/thrstat001.cpp Tue Nov 26 10:22:13 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, 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
@@ -39,63 +39,72 @@
static jvmtiCapabilities caps;
static jvmtiEventCallbacks callbacks;
static jrawMonitorID access_lock;
+static jrawMonitorID wait_lock;
static jint result = PASSED;
-static jboolean printdump = JNI_FALSE;
static jthread thr_ptr = NULL;
+
static jint state[] = {
JVMTI_THREAD_STATE_RUNNABLE,
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
JVMTI_THREAD_STATE_IN_OBJECT_WAIT
};
-static int entry_count = 0;
-static int entry_error_count = 0;
-static int exit_count = 0;
-static int exit_error_count = 0;
+static void
+lock(const char* func_name, jrawMonitorID lock) {
+ jvmtiError err = jvmti->RawMonitorEnter(lock);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("%s: unexpected error in RawMonitorEnter: %s (%d)\n",
+ func_name, TranslateError(err), err);
+ result = STATUS_FAILED;
+ }
+}
-void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) {
- jvmtiError err;
-
- err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
- JVMTI_EVENT_THREAD_START, NULL);
+static void
+unlock(const char* func_name, jrawMonitorID lock) {
+ jvmtiError err = jvmti->RawMonitorExit(lock);
if (err != JVMTI_ERROR_NONE) {
- printf("Failed to enable THREAD_START event: %s (%d)\n",
- TranslateError(err), err);
+ printf("%s: unexpected error in RawMonitorExit: %s (%d)\n",
+ func_name, TranslateError(err), err);
result = STATUS_FAILED;
}
+}
- if (caps.can_generate_method_entry_events) {
- err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
- JVMTI_EVENT_METHOD_ENTRY, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf("Failed to enable METHOD_ENTRY event: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
+static void
+wait(const char* func_name, jrawMonitorID lock, jint millis) {
+ jvmtiError err = jvmti->RawMonitorWait(lock, (jlong)millis);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("%s: unexpected error in RawMonitorWait: %s (%d)\n",
+ func_name, TranslateError(err), err);
+ result = STATUS_FAILED;
}
+}
- if (caps.can_generate_method_exit_events) {
- err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
- JVMTI_EVENT_METHOD_EXIT, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf("Failed to enable METHOD_EXIT event: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
+static void
+set_notification_mode(const char* event_name,
+ jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread) {
+ const char* action = (mode == JVMTI_ENABLE) ? "enable" : "disable";
+ jvmtiError err = jvmti->SetEventNotificationMode(mode, event_type, event_thread);
+
+ if (err != JVMTI_ERROR_NONE) {
+ printf("Failed to %s %s event: %s (%d)\n",
+ action, event_name, TranslateError(err), err);
+ result = STATUS_FAILED;
}
}
+void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) {
+ set_notification_mode("JVMTI_EVENT_THREAD_START", JVMTI_ENABLE,
+ JVMTI_EVENT_THREAD_START, NULL);
+}
+
void JNICALL
ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) {
jvmtiError err;
jvmtiThreadInfo thrInfo;
- err = jvmti_env->RawMonitorEnter(access_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorEnter#TS) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
+ lock("ThreadStart", access_lock);
err = jvmti_env->GetThreadInfo(thread, &thrInfo);
if (err != JVMTI_ERROR_NONE) {
@@ -105,111 +114,12 @@
}
if (thrInfo.name != NULL && strcmp(thrInfo.name, "thr1") == 0) {
thr_ptr = env->NewGlobalRef(thread);
- if (printdump == JNI_TRUE) {
- printf(">>> ThreadStart: \"%s\", 0x%p\n", thrInfo.name, thr_ptr);
- }
- }
-
- err = jvmti_env->RawMonitorExit(access_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorExit#TS) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
-}
-
-void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *env,
- jthread thread, jmethodID mid) {
- jvmtiError err;
- jvmtiThreadInfo thrInfo;
- jint thrState;
-
- err = jvmti_env->RawMonitorEnter(access_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorEnter#ME) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
-
- entry_count++;
- err = jvmti_env->GetThreadState(thread, &thrState);
- if (err != JVMTI_ERROR_NONE) {
- printf("(GetThreadState#ME) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- if ((thrState & JVMTI_THREAD_STATE_RUNNABLE) == 0) {
- if (entry_error_count == 0) {
- err = jvmti_env->GetThreadInfo(thread, &thrInfo);
- if (err != JVMTI_ERROR_NONE) {
- printf("(GetThreadInfo#ME) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- printf("Wrong thread \"%s\" state on MethodEntry event:\n",
- thrInfo.name);
- printf(" expected: JVMTI_THREAD_STATE_RUNNABLE\n");
- printf(" got: %s (%d)\n",
- TranslateState(thrState), thrState);
- }
- entry_error_count++;
- result = STATUS_FAILED;
+ printf(">>> ThreadStart: \"%s\", 0x%p\n", thrInfo.name, thr_ptr);
+ set_notification_mode("JVMTI_EVENT_THREAD_START", JVMTI_DISABLE,
+ JVMTI_EVENT_THREAD_START, NULL);
}
- err = jvmti_env->RawMonitorExit(access_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorExit#ME) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
-
-}
-
-void JNICALL MethodExit(jvmtiEnv *jvmti_env, JNIEnv *env,
- jthread thread, jmethodID mid,
- jboolean was_poped_by_exception, jvalue return_value) {
- jvmtiError err;
- jvmtiThreadInfo thrInfo;
- jint thrState;
-
- err = jvmti_env->RawMonitorEnter(access_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorEnter#MX) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
-
- exit_count++;
- err = jvmti_env->GetThreadState(thread, &thrState);
- if (err != JVMTI_ERROR_NONE) {
- printf("(GetThreadState#MX) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- if ((thrState & JVMTI_THREAD_STATE_RUNNABLE) == 0) {
- if (exit_error_count == 0) {
- err = jvmti_env->GetThreadInfo(thread, &thrInfo);
- if (err != JVMTI_ERROR_NONE) {
- printf("(GetThreadInfo#MX) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- printf("Wrong thread \"%s\" state on MethodExit event:\n",
- thrInfo.name);
- printf(" expected: JVMTI_THREAD_STATE_RUNNABLE\n");
- printf(" got: %s (%d)\n",
- TranslateState(thrState), thrState);
- }
- exit_error_count++;
- result = STATUS_FAILED;
- }
-
- err = jvmti_env->RawMonitorExit(access_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorExit#MX) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
+ unlock("ThreadStart", access_lock);
}
#ifdef STATIC_BUILD
@@ -223,13 +133,12 @@
return JNI_VERSION_1_8;
}
#endif
+
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
jint res;
jvmtiError err;
- if (options != NULL && strcmp(options, "printdump") == 0) {
- printdump = JNI_TRUE;
- }
+ printf("Agent_Initialize started\n");
res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
if (res != JNI_OK || jvmti == NULL) {
@@ -260,23 +169,20 @@
err = jvmti->CreateRawMonitor("_access_lock", &access_lock);
if (err != JVMTI_ERROR_NONE) {
- printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
+ printf("(CreateRawMonitor)#access_lock unexpected error: %s (%d)\n",
+ TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = jvmti->CreateRawMonitor("_wait_lock", &wait_lock);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("(CreateRawMonitor#wait_lock) unexpected error: %s (%d)\n",
TranslateError(err), err);
return JNI_ERR;
}
callbacks.VMInit = &VMInit;
callbacks.ThreadStart = &ThreadStart;
- if (caps.can_generate_method_entry_events) {
- callbacks.MethodEntry = &MethodEntry;
- } else {
- printf("Warning: MethodEntry event is not implemented\n");
- }
- if (caps.can_generate_method_exit_events) {
- callbacks.MethodExit = &MethodExit;
- } else {
- printf("Warning: MethodExit event is not implemented\n");
- }
err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
if (err != JVMTI_ERROR_NONE) {
printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
@@ -284,14 +190,10 @@
return JNI_ERR;
}
- err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
- JVMTI_EVENT_VM_INIT, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf("Failed to enable VM_INIT event: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
+ set_notification_mode("JVMTI_EVENT_VM_INIT", JVMTI_ENABLE,
+ JVMTI_EVENT_VM_INIT, NULL);
+ printf("Agent_Initialize finished\n\n");
return JNI_OK;
}
@@ -299,10 +201,10 @@
Java_nsk_jvmti_GetThreadState_thrstat001_checkStatus(JNIEnv *env,
jclass cls, jint statInd) {
jvmtiError err;
- jrawMonitorID wait_lock;
jint thrState;
jint millis;
+ printf("native method checkStatus started\n");
if (jvmti == NULL) {
printf("JVMTI client was not properly loaded!\n");
result = STATUS_FAILED;
@@ -316,12 +218,6 @@
}
/* wait until thread gets an expected state */
- err = jvmti->CreateRawMonitor("_wait_lock", &wait_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
for (millis = WAIT_START; millis < WAIT_TIME; millis <<= 1) {
err = jvmti->GetThreadState(thr_ptr, &thrState);
if (err != JVMTI_ERROR_NONE) {
@@ -332,36 +228,13 @@
if ((thrState & state[statInd]) != 0) {
break;
}
- err = jvmti->RawMonitorEnter(wait_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorEnter) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- err = jvmti->RawMonitorWait(wait_lock, (jlong)millis);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorWait) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- err = jvmti->RawMonitorExit(wait_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(RawMonitorExit) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- }
- err = jvmti->DestroyRawMonitor(wait_lock);
- if (err != JVMTI_ERROR_NONE) {
- printf("(DestroyRawMonitor) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
+ lock("checkStatus", wait_lock);
+ wait("checkStatus", wait_lock, millis);
+ unlock("checkStatus", wait_lock);
}
- if (printdump == JNI_TRUE) {
- printf(">>> thread \"thr1\" (0x%p) state: %s (%d)\n",
+ printf(">>> thread \"thr1\" (0x%p) state: %s (%d)\n",
thr_ptr, TranslateState(thrState), thrState);
- }
if ((thrState & state[statInd]) == 0) {
printf("Wrong thread \"thr1\" (0x%p) state:\n", thr_ptr);
@@ -371,55 +244,12 @@
TranslateState(thrState), thrState);
result = STATUS_FAILED;
}
+ printf("native method checkStatus finished\n\n");
}
JNIEXPORT jint JNICALL
Java_nsk_jvmti_GetThreadState_thrstat001_getRes(JNIEnv *env, jclass cls) {
- jvmtiError err;
-
- err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,
- JVMTI_EVENT_THREAD_START, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf("Failed to disable THREAD_START event: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
-
- if (caps.can_generate_method_entry_events) {
- err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,
- JVMTI_EVENT_METHOD_ENTRY, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf("Failed to disable METHOD_ENTRY event: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- }
-
- if (caps.can_generate_method_exit_events) {
- err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,
- JVMTI_EVENT_METHOD_EXIT, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf("Failed to disable METHOD_EXIT event: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- }
- }
-
- if (printdump == JNI_TRUE) {
- printf(">>> total number of method entry events = %d\n", entry_count);
- printf(">>> total number of method exit events = %d\n", exit_count);
- }
-
- if (entry_error_count != 0) {
- printf("Total number of errors on METHOD_ENTRY: %d of %d events\n",
- entry_error_count, entry_count);
- }
-
- if (exit_error_count != 0) {
- printf("Total number of errors on METHOD_EXIT: %d of %d events\n",
- exit_error_count, exit_count);
- }
-
+ printf("native method getRes: result: %d\n\n", result);
return result;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/methodReference/ProtectedInaccessibleMethodRefTest2.java Tue Nov 26 10:22:13 2019 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019, 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 8234729
+ * @summary Javac should eagerly change code generation for method references to avert IllegalAccessError in future.
+ * @run main ProtectedInaccessibleMethodRefTest2
+ */
+
+import pack.I;
+import pack.J;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.Function;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+public final class ProtectedInaccessibleMethodRefTest2 extends I {
+
+ public static void main(String... args) {
+ ProtectedInaccessibleMethodRefTest2 m = new ProtectedInaccessibleMethodRefTest2();
+ m.test(Paths.get("test"));
+ // Verify that the method reference has been folded into a lambda.
+ boolean lambdaFound = false;
+ for (Method meth : ProtectedInaccessibleMethodRefTest2.class.getDeclaredMethods()) {
+ if (meth.getName().equals("lambda$test$0")) {
+ lambdaFound = true;
+ break;
+ }
+ }
+ if (!lambdaFound) {
+ throw new AssertionError("Did not find evidence of new code generation");
+ }
+ }
+
+ void test(Path outputDir) {
+ Sub c = new Sub(this::readFile);
+ c.check(outputDir);
+ }
+ public class Sub extends J {
+ Sub(Function<Path,String> fileReader) {
+ super(fileReader);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/methodReference/pack/I.java Tue Nov 26 10:22:13 2019 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package pack;
+
+import java.nio.file.Path;
+
+public class I {
+ protected String readFile(Path file) {
+ return file.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/methodReference/pack/J.java Tue Nov 26 10:22:13 2019 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package pack;
+
+import java.nio.file.Path;
+import java.util.function.Function;
+
+public class J {
+ protected final Function<Path,String> fileReader;
+
+ public J(Function<Path,String> fileReader) {
+ this.fileReader = fileReader;
+ }
+
+ protected void checkFile(Path file) {
+ fileReader.apply(file);
+ }
+
+ public void check(Path file) {
+ checkFile(file);
+ }
+}