1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp
index 9cafbd1..e24f8c9 100644
--- a/src/share/vm/prims/jvmtiEnv.cpp
+++ b/src/share/vm/prims/jvmtiEnv.cpp
@@ -298,10 +298,12 @@
//TODO: add locking
if (AllowEnhancedClassRedefinition) {
VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
+ MutexLocker sd_mutex(RedefineClasses_lock);
VMThread::execute(&op);
return (op.check_error());
}
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
+ MutexLocker sd_mutex(RedefineClasses_lock);
VMThread::execute(&op);
return (op.check_error());
} /* end RedefineClasses */
diff --git a/src/share/vm/runtime/mutexLocker.cpp b/src/share/vm/runtime/mutexLocker.cpp
index f358c75..02377a4 100644
--- a/src/share/vm/runtime/mutexLocker.cpp
+++ b/src/share/vm/runtime/mutexLocker.cpp
@@ -38,6 +38,7 @@
// Consider using GCC's __read_mostly.
Mutex* Patching_lock = NULL;
+Mutex* RedefineClasses_lock = NULL;
Monitor* SystemDictionary_lock = NULL;
Mutex* PackageTable_lock = NULL;
Mutex* CompiledIC_lock = NULL;
@@ -279,6 +280,7 @@
def(ProfileVM_lock , Monitor, special, false); // used for profiling of the VMThread
def(CompileThread_lock , Monitor, nonleaf+5, false );
def(PeriodicTask_lock , Monitor, nonleaf+5, true);
+ def(RedefineClasses_lock , Mutex , nonleaf+7, false ); // for ensuring that class redefinition is not done in parallel
#ifdef INCLUDE_TRACE
def(JfrMsg_lock , Monitor, leaf, true);
diff --git a/src/share/vm/runtime/mutexLocker.hpp b/src/share/vm/runtime/mutexLocker.hpp
index be86bac..a77f546 100644
--- a/src/share/vm/runtime/mutexLocker.hpp
+++ b/src/share/vm/runtime/mutexLocker.hpp
@@ -46,6 +46,7 @@
// Mutexes used in the VM.
extern Mutex* Patching_lock; // a lock used to guard code patching of compiled code
+extern Mutex* RedefineClasses_lock; // a lock on class redefinition
extern Monitor* SystemDictionary_lock; // a lock on the system dictonary
extern Mutex* PackageTable_lock; // a lock on the class loader package table
extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
index 0dc86d9..9f4c2e9 100644
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
@@ -910,6 +910,15 @@
return false;
}
+bool Thread::owns_locks_but_redefine_classes_lock() const {
+ for(Monitor *cur = _owned_locks; cur; cur = cur->next()) {
+ if (cur != RedefineClasses_lock && cur->rank() != Mutex::redefine_classes) {
+ return true;
+ }
+ }
+ return false;
+}
+
#endif
diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp
index 1117c87..77b716c 100644
--- a/src/share/vm/runtime/thread.hpp
+++ b/src/share/vm/runtime/thread.hpp
@@ -211,11 +211,14 @@
void enter_signal_handler() { _num_nested_signal++; }
void leave_signal_handler() { _num_nested_signal--; }
bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
+ Mutex* redefine_classes_mutex() { return _redefine_classes_mutex; }
private:
// Debug tracing
static void trace(const char* msg, const Thread* const thread) PRODUCT_RETURN;
+ Mutex* _redefine_classes_mutex;
+
// Active_handles points to a block of handles
JNIHandleBlock* _active_handles;
@@ -585,6 +588,7 @@
void print_owned_locks() const { print_owned_locks_on(tty); }
Monitor* owned_locks() const { return _owned_locks; }
bool owns_locks() const { return owned_locks() != NULL; }
+ bool owns_locks_but_redefine_classes_lock() const;
bool owns_locks_but_compiled_lock() const;
// Deadlock detection
|