United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6444286 Possible naked oop related to biased locking revocation safepoint in jni_exit()
JDK-6444286 : Possible naked oop related to biased locking revocation safepoint in jni_exit()

Details
Type:
Bug
Submit Date:
2006-06-28
Status:
Resolved
Updated Date:
2013-06-26
Project Name:
JDK
Resolved Date:
2013-01-22
Component:
hotspot
OS:
generic
Sub-Component:
runtime
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:
hs25 (b17)

Related Reports
Backport:
Backport:
Backport:
Backport:

Sub Tasks

Description
jni_exit() should box and unbox the naked oop into a handle over the call to revoke bias.  FastHashCode() serves as good model.

                                    

Comments
EVALUATION

should fix.
                                     
2010-11-10
Testing the fix for this bug requires the proper alignment of the stars,
the moon and a few of the planets:

- -XX:+UseBiasedLocking option
- a JNI MonitorExit() call on an appropriately biased Java object
- a GC operation that moves the appropriately biased Java object
  in such a way that access to the memory that used to contain
  that Java object now blows up

The last item above is the tricky one. It is entirely possible for GC to
relocate the appropriately biased Java object and for the subsequent
access of the memory that used to contain that Java object to _not_
blow up.

An alternative is to create a test that exercises the code path in
question:

::::::::::::::
UnsafeJNIMonitorTest.java
::::::::::::::
//
// Run this test with the following command:
//
// $JAVA_HOME/fastdebug/bin/java \
//     -XX:+UseBiasedLocking \
//     -Xbootclasspath/p:. \
//     UnsafeJNIMonitorTest
//

import sun.misc.Unsafe;

public class UnsafeJNIMonitorTest {
    private static final Unsafe unsafe = Unsafe.getUnsafe();

    public static void main(String[] args) {
        System.out.println("Hello from UnsafeJNIMonitorTest!");

        Object dummy = new Object();
        unsafe.monitorEnter(dummy);
        System.out.println("Entered dummy monitor.");
        unsafe.monitorExit(dummy);
        System.out.println("Exited dummy monitor.");
    }
}
::::::::::::::
doit.sh
::::::::::::::
set -x
$JAVA_HOME/bin/java \
    "$@" \
    -XX:+UseBiasedLocking \
    -Xbootclasspath/p:. \
    UnsafeJNIMonitorTest

Now you need a VM with the following modifications:

diff -r 97ee8abd6ab2 src/share/vm/runtime/biasedLocking.cpp
--- a/src/share/vm/runtime/biasedLocking.cpp    Wed Jan 09 12:10:25 2013 -0800
+++ b/src/share/vm/runtime/biasedLocking.cpp    Thu Jan 10 16:52:31 2013 -0700
@@ -527,6 +527,12 @@ BiasedLocking::Condition BiasedLocking::
 BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) {
   assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint");
 
+if (Threads::number_of_threads() > 0) {
+// don't do the dummy safepoint until main is up and running
+VM_ForceSafepoint dummy_safepoint;
+VMThread::execute(&dummy_safepoint);
+}
+
   // We can revoke the biases of anonymously-biased objects
   // efficiently enough that we should not cause these revocations to
   // update the heuristics because doing so may cause unwanted bulk


diff -r 97ee8abd6ab2 src/share/vm/runtime/synchronizer.cpp
--- a/src/share/vm/runtime/synchronizer.cpp     Wed Jan 09 12:10:25 2013 -0800
+++ b/src/share/vm/runtime/synchronizer.cpp     Thu Jan 10 16:52:31 2013 -0700
@@ -333,6 +333,7 @@ void ObjectSynchronizer::jni_exit(oop ob
 void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
   TEVENT (jni_exit) ;
   if (UseBiasedLocking) {
+No_Safepoint_Verifier nsv;
     BiasedLocking::revoke_and_rebias(obj, false, THREAD);
   }
   assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");


The change in src/share/vm/runtime/synchronizer.cpp simply add a
No_Safepoint_Verifier helper object right before the questionable
call to BiasedLocking::revoke_and_rebias(obj, false, THREAD);

The change in src/share/vm/runtime/biasedLocking.cpp simply
forces a safepoint to happen in BiasedLocking::revoke_and_rebias()
once the VM has gotten up to the point where the main thread is
running. If you look at the logic in BiasedLocking::revoke_and_rebias(),
you'll see there are many different paths that can cause a safepoint.


Here's the output when you run the test:

+ /work/local/jdk/1.8.0/solaris-x64/bin/java -client_bh_hsx_rt_latest_exp_dcubed-fast -showversion -XX:+UseBiasedLocking -Xbootclasspath/p:. UnsafeJNIMonitorTest 
Java HotSpot(TM) Client VM warning: Thread holding lock at safepoint that vm can block on: MethodCompileQueue_lock
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b71)
Java HotSpot(TM) Client VM (build 25.0-b15-bh_hsx_rt_latest_exp_dcubed-product-fastdebug, mixed mode)

Hello from UnsafeJNIMonitorTest!
Entered dummy monitor.
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/thread.cpp:911
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/work/shared/bug_hunt/hsx_rt_latest/exp/src/share/vm/runtime/thread.cpp:911), pid=19176, tid=2
#  fatal error: Possible safepoint reached by thread that does not allow it
#
# JRE version: Java(TM) SE Runtime Environment (8.0-b71) (build 1.8.0-ea-b71)
# Java VM: Java HotSpot(TM) Client VM (25.0-b15-bh_hsx_rt_latest_exp_dcubed-product-fastdebug mixed mode solaris-x86 )
# Core dump written. Default location: /work/shared/bugs/6444286/core or core.19176
#
# An error report file with more information is saved as:
# /work/shared/bugs/6444286/hs_err_pid19176.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#
Current thread is 2
Dumping core ...
Abort - core dumped

And here's the crashing thread's stack:

---------------  T H R E A D  ---------------

Current thread (0x0806c000):  JavaThread "main" [_thread_in_vm, id=2, stack(0xfc
eef000,0xfcf3f000)]

Stack: [0xfceef000,0xfcf3f000],  sp=0xfcf3df00,  free space=315k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x1591cc9]  void VMError::report(outputStream*)+0x92d
V  [libjvm.so+0x1592f4e]  void VMError::report_and_die()+0x57a
V  [libjvm.so+0x78a8bf]  void report_fatal(const char*,int,const char*)+0x56f
V  [libjvm.so+0x148f252]  void Thread::check_for_valid_safepoint_state(bool)+0x1
56
V  [libjvm.so+0x15bcafe]  void VMThread::execute(VM_Operation*)+0x1f6
V  [libjvm.so+0x2f2796]  BiasedLocking::Condition BiasedLocking::revoke_and_rebi
as(Handle,bool,Thread*)+0x66
V  [libjvm.so+0x14071fd]  void ObjectSynchronizer::jni_exit(oop,Thread*)+0x189
V  [libjvm.so+0x1535c62]  Unsafe_MonitorExit+0x4fa
j  sun.misc.Unsafe.monitorExit(Ljava/lang/Object;)V+0
j  UnsafeJNIMonitorTest.main([Ljava/lang/String;)V+35


                                     
2013-01-11
See https://jbs.oracle.com/bugs/browse/JDK-8004902 for the webrevs used during Code Review Round [012] for this fix. 
                                     
2013-01-17
URL:   http://hg.openjdk.java.net/hsx/hotspot-rt/hotspot/rev/f3184f32ce0b
User:  dcubed
Date:  2013-01-22 18:35:08 +0000

                                     
2013-01-22
URL:   http://hg.openjdk.java.net/hsx/hsx25/hotspot/rev/f3184f32ce0b
User:  amurillo
Date:  2013-01-25 20:42:57 +0000

                                     
2013-01-25



Hardware and Software, Engineered to Work Together