-
Bug
-
Resolution: Fixed
-
P2
-
16, 17, 18
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8273908 | 17.0.2 | Volker Simonis | P2 | Closed | Fixed | b01 |
Currently, OopHandle::release() is implemented as follows:
inline void OopHandle::release(OopStorage* storage) {
if (peek() != NULL) {
// Clear the OopHandle first
NativeAccess<>::oop_store(_obj, (oop)NULL);
storage->release(_obj);
}
}
However, peek() returns NULL not only if the oop* `_obj` is NULL, but also when `_obj` points to a zero oop. In the latter case, the oop* `_obj` will not be released from the corresponding OopStorage and the slot it occupies will remain alive forever.
This behavior can be easily triggered with the attached LeakTestMinimal.java test (thanks to Oli Gillespie from the Amazon Profiler team for detecting the issue and providing a reproducer).
The fix is trivial:
diff --git a/src/hotspot/share/oops/oopHandle.inline.hpp b/src/hotspot/share/oops/oopHandle.inline.hpp
index 44362499a2c..20de5146ec3 100644
--- a/src/hotspot/share/oops/oopHandle.inline.hpp
+++ b/src/hotspot/share/oops/oopHandle.inline.hpp
@@ -48,7 +48,7 @@ inline OopHandle::OopHandle(OopStorage* storage, oop obj) :
}
inline void OopHandle::release(OopStorage* storage) {
- if (peek() != NULL) {
+ if (_obj != NULL) {
// Clear the OopHandle first
NativeAccess<>::oop_store(_obj, (oop)NULL);
storage->release(_obj);
inline void OopHandle::release(OopStorage* storage) {
if (peek() != NULL) {
// Clear the OopHandle first
NativeAccess<>::oop_store(_obj, (oop)NULL);
storage->release(_obj);
}
}
However, peek() returns NULL not only if the oop* `_obj` is NULL, but also when `_obj` points to a zero oop. In the latter case, the oop* `_obj` will not be released from the corresponding OopStorage and the slot it occupies will remain alive forever.
This behavior can be easily triggered with the attached LeakTestMinimal.java test (thanks to Oli Gillespie from the Amazon Profiler team for detecting the issue and providing a reproducer).
The fix is trivial:
diff --git a/src/hotspot/share/oops/oopHandle.inline.hpp b/src/hotspot/share/oops/oopHandle.inline.hpp
index 44362499a2c..20de5146ec3 100644
--- a/src/hotspot/share/oops/oopHandle.inline.hpp
+++ b/src/hotspot/share/oops/oopHandle.inline.hpp
@@ -48,7 +48,7 @@ inline OopHandle::OopHandle(OopStorage* storage, oop obj) :
}
inline void OopHandle::release(OopStorage* storage) {
- if (peek() != NULL) {
+ if (_obj != NULL) {
// Clear the OopHandle first
NativeAccess<>::oop_store(_obj, (oop)NULL);
storage->release(_obj);
- backported by
-
JDK-8273908 Memory leak in OopStorage due to bug in OopHandle::release()
- Closed
- duplicates
-
JDK-8280240 Native memory leak growing (serviceability category) when doing thread dumps
- Closed
- relates to
-
JDK-8247878 Move Management strong oops to OopStorage
- Resolved
- links to
-
Commit openjdk/jdk17u/926a815f
-
Commit openjdk/jdk/bc48a0ac
-
Review openjdk/jdk17u/79
-
Review openjdk/jdk/5549
(2 links to)