现在不太清楚,

    public static void main(String[] args) {

        Object object=new Object();
System.out.println("before synchronized start");
synchronized (object) {
int am =object.hashCode();
System.out.println("start");
synchronized (object) {
int a=object.hashCode();
System.out.println("inner"); }
System.out.println("end"); }

断点

//%note monitor_1
IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
#ifdef ASSERT
thread->last_frame().interpreter_frame_verify_monitor(elem);
#endif
if (PrintBiasedLockingStatistics) {
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
}
Handle h_obj(thread, elem->obj());
assert(Universe::heap()->is_in_reserved_or_null(h_obj()),
"must be NULL or an object");
if (UseBiasedLocking) {
// Retry fast entry if bias is revoked to avoid unnecessary inflation
ObjectSynchronizer::fast_enter(h_obj, elem->lock(), true, CHECK);
} else {
ObjectSynchronizer::slow_enter(h_obj, elem->lock(), CHECK);
}
assert(Universe::heap()->is_in_reserved_or_null(elem->obj()),
"must be NULL or an object");
#ifdef ASSERT
thread->last_frame().interpreter_frame_verify_monitor(elem);
#endif
IRT_END

这个只会在嵌套的第二个里面,搞不懂,为什么第一次不会再第一次synchronized进入

通过thread打印栈帧

(gdb) x/50xg 0x7f8c1cd976d0
0x7f8c1cd976d0: 0xffffffffdb26d002 BasicObjectLock
0x00000000f3886948
0x7f8c1cd976e0: 0x0000000000000001
0x00000000f3886948 obj
0x7f8c1cd976f0: 0x00007f8c1cd976d0 -8
0x00007f8c192357be -7
0x7f8c1cd97700: 0x00007f8c1cd97798 -6
0x00007f8c19235aa8 -5
0x7f8c1cd97710: 0x0000000000000000 -4
0x00007f8c192359c8 -3
0x7f8c1cd97720: 0x0000000000000000 -2
0x00007f8c1cd97798 -1
0x7f8c1cd97730: 0x00007f8c1cd97800 fp()
0x00007f8c05000671
0x7f8c1cd97740: 0x0000000000000000
0x0000000000000000
0x7f8c1cd97750: 0x0000000000000000
0x0000000000000000
0x7f8c1cd97760: 0x0000000000000000
0x0000000000000000
0x7f8c1cd97770: 0x0000000000000000
0x00000000f3886948
0x7f8c1cd97780: 0x0000000033909752
0x00000000f3886948 0bj
0x7f8c1cd97790: 0x00000000f3886948 obj
0x00000000f3886938 args[]
0x7f8c1cd977a0: 0x00007f8c00001fa0 -12
0x00007f8c1cd98700 -11
0x7f8c1cd977b0: 0x0000000000000000 -10
0x00007f8c1cd97b40 -9
0x7f8c1cd977c0: 0x0000000000000001 -8
0x00007f8c05000564 -7
0x7f8c1cd977d0: 0x00007f8c1cd97880 -6
0x00007f8c1cd97d28 -5
0x7f8c1cd977e0: 0x00007f8c0000000a -4
0x00007f8c192359c8 -3
0x7f8c1cd977f0: 0x00007f8c0501e2e0 -2
0x00007f8c1cd97b40 -1
0x7f8c1cd97800: 0x00007f8c1cd97a40 saved rbp
0x00007f8c1b486e2e return addr
0x7f8c1cd97810: 0x0000000000000001 param size
0x00007f8c1400b800 thread
0x7f8c1cd97820: 0x00007f8c1400b800
0x00007f8c1cd97b30
0x7f8c1cd97830: 0x00007f8c1cd97c50 0x00007f8c1cd97d20
0x7f8c1cd97840: 0x00007f8c1400b800 0x00007f8c1400c078
0x7f8c1cd97850: 0x00007f8c1400c0e8 0x00007f8c1400c108

sp头顶是是elem

(gdb) p * elem
$1 = {_lock = {_displaced_header = 0xffffffffdbae1002}, _obj = 0xf3886978}

那么看下BasicObjectLock定义

class BasicObjectLock VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
BasicLock _lock; // the lock, must be double word aligned
oop _obj; // object holds the lock; public:
// Manipulation
....
};
(gdb) p elem._lock
$3 = {_displaced_header = 0xffffffffdbae1002}

那看下lock定义

class BasicLock VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
volatile markOop _displaced_header;
public:
markOop displaced_header() const { return _displaced_header; }
void set_displaced_header(markOop header) { _displaced_header = header; } void print_on(outputStream* st) const; // move a basic lock (used during deoptimization
void move_to(oop obj, BasicLock* dest); static int displaced_header_offset_in_bytes() { return offset_of(BasicLock, _displaced_header); }
};

就是记录的一个markOop头

  enum { locked_value             = 0, //轻量级
unlocked_value = 1, //无锁
monitor_value = 2, 重量级
marked_value = 3,
biased_lock_pattern = 5 偏向锁
};

那么打印一下这个oop中指示的互斥锁对象

(gdb) p * inf
$43 = {
static SpinCallbackFunction = 0x0,
static SpinCallbackArgument = 0,
_header = 0x3390975201,
_object = 0xf3886978,
SharingPad = {-7.4786357953083842e+240},
_owner = 0x7f24b05236e0,
_previous_owner_tid = 0,
_recursions = 0,
OwnerIsThread = 0,
_cxq = 0x0,
_EntryList = 0x0,
_succ = 0x0,
_Responsible = 0x0,
_PromptDrain = -235802127,
_Spinner = -235802127,
_SpinFreq = 0,
_SpinClock = 0,
_SpinDuration = 5000,
_SpinState = -1012762419733073423,
_count = 0,
_waiters = 0,
_WaitSet = 0x0,
_WaitSetLock = 0,
_QMix = -235802127,
FreeNext = 0x0,
StatA = -1012762419733073423,
StatsB = -1012762419733073423,
static _sync_ContendedLockAttempts = 0x7f24a800d8f8,
static _sync_FutileWakeups = 0x7f24a800d9c8,
static _sync_Parks = 0x7f24a800da88,
static _sync_EmptyNotifications = 0x7f24a800db48,
static _sync_Notifications = 0x7f24a800dc08,
static _sync_SlowEnter = 0x7f24a800dcc8,
static _sync_SlowExit = 0x7f24a800dd88,
static _sync_SlowNotify = 0x7f24a800de48,
static _sync_SlowNotifyAll = 0x7f24a800df08,
static _sync_FailedSpins = 0x0,
static _sync_SuccessfulSpins = 0x7f24a800e088,
static _sync_PrivateA = 0x7f24a800e148,
static _sync_PrivateB = 0x7f24a800e208,
static _sync_MonInCirculation = 0x7f24a800e2c8,
static _sync_MonScavenged = 0x7f24a800e388,
static _sync_Inflations = 0x7f24a800d378,
static _sync_Deflations = 0x7f24a800d838,
static _sync_MonExtant = 0x7f24a800e448,
static Knob_Verbose = 0,
static Knob_SpinLimit = 5000
}
(gdb) p object
$44 = (oopDesc *) 0xf3886978

jvm源码解读--16 锁_开头的更多相关文章

  1. jvm源码解读--16 cas 用法解析

    CAS的意思是campare and sweep比较交换 这个如果不用代码会比较抽象,那么在源码中进行解释 void ATTR ObjectMonitor::enter(TRAPS) { // The ...

  2. JVM 源码解读之 CMS 何时会进行 Full GC

    t点击上方"涤生的博客",关注我 转载请注明原创出处,谢谢!如果读完觉得有收获的话,欢迎点赞加关注. 前言 本文内容是基于 JDK 8 在文章 JVM 源码解读之 CMS GC 触 ...

  3. synchronized的jvm源码分析聊锁的意义

    上篇写完了ReentrantLock源码实现,从我们的角度分析设计锁,在对比大神的实现,顺道拍了一波道哥的马屁,虽然他看不到,哈哈.这一篇我们来聊一聊synchronized的源码实现,并对比reen ...

  4. jvm源码解读--17 Java的wait()、notify()学习

    write and debug by 张艳涛 wait()和notify()的通常用法 A线程取得锁,执行wait(),释放锁; B线程取得锁,完成业务后执行notify(),再释放锁; B线程释放锁 ...

  5. jvm源码解读--11 ldc指令的解读

    写一个java文件 public static void main(String[] args) { String str1="abc"; String str2 ="a ...

  6. jvm源码解读--08 创建oop对象,将static静态变量放置在oop的96 offset处

    之前分析的已经加载的.Class文件中都没有Static 静态变量,所以也就没这部分的解析,自己也是不懂hotspot 将静态变量放哪里去了,追踪源码之后,看清楚了整个套路,总体上来说,可以举例来说对 ...

  7. Redisson源码解读-分布式锁

    前言 Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid).Redisson有一样功能是可重入的分布式锁.本文来讨论一下这个功能的特点以及源 ...

  8. jvm源码解读--13 gc_root中的栈中oop的mark 和copy 过程分析

    粘贴源码 package com.test; import java.util.Random; public class Test { static int number=12; private in ...

  9. Redisson源码解读-公平锁

    前言 我在上一篇文章聊了Redisson的可重入锁,这次继续来聊聊Redisson的公平锁.下面是官方原话: 它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程.所有请 ...

随机推荐

  1. Centos8.3、mysql8.0主从复制实战记录

    引言 最近又上线了一个项目,感觉自己这段时间收获不少就想把自己做这个项目用的技术总结梳理一下.这个项目是我自己发起,领导们不是特别重视所以得到资源有限,资源有限的情况我只能选择手动搭建数据库环境,资源 ...

  2. csp-s模拟测试「9.14」A·B·C(三分,贪心)

    博客大概咕了很久了......... T1 A 大概推下式子就好了,考试时数据点分治DFS前30点T了,然后后70分因为两数相乘爆long long然后本来可以A掉,就WA零了....... 式子推出 ...

  3. Netty 框架学习 —— 引导

    概述 前面我们学习了 ChannelPipeline.ChannelHandler 和 EventLoop 之后,接下来的问题是:如何将它们组织起来,成为一个可实际运行的应用程序呢?答案是使用引导(B ...

  4. C程序从编译到运行

    第一篇文章 一.前言 最近在看CSAPP(深入理解计算机系统)然后以前也学过C语言,但是从来没有深究写好的C代码是怎么编译再到执行的. 所以现在自己学习,然后记录下来. 以最常用的hello worl ...

  5. 『动善时』JMeter基础 — 50、使用JMeter测试WebService接口

    目录 1.什么是WebService 2.WebService和SOAP的关系 3.什么是WSDL 4.测试WebService接口前的准备 (1)如何判断是WebService接口 (2)如何获取W ...

  6. Java基础篇(JVM)——类加载机制

    这是Java基础篇(JVM)的第二篇文章,紧接着上一篇字节码详解,这篇我们来详解Java的类加载机制,也就是如何把字节码代表的类信息加载进入内存中. 我们知道,不管是根据类新建对象,还是直接使用类变量 ...

  7. MiniSMB 专业网络性能测试仪表 英特尔82576 4*1GE 网卡性能测试报告

    MiniSMB 专业网络性能测试仪表英特尔82576 4*1GE网卡性能测试报告 一.测试环境 测试配置 ①工控机配置: CPU:Intel(R) Core(TM) i7-6800K CPU @ 3. ...

  8. Elasticsearch查询文档总数

    前言 在使用ES搜索的时候,或多或少都会面临查询数据总量的情况,下面介绍三种查询数据总量的方式. 其中,方案二解决了当结果数据总量超过1w时,由于ES默认设置(max_result_window:10 ...

  9. 阿里P7大佬带你解密Sentinel

    概述 在接连写了两篇关于限流的文章(<面试补习>- 你来说说什么是限流?, 限流神器Sentinel,不了解一下吗?)后,总感觉还差最后一点内容来闭环整个限流相关的内容,这两天在翻查相关文 ...

  10. mui 移动端网页双击事件处理

    使用场景:需要在动态生成li列表数据中添加双击事件 定义事件 : var date1=null; function listdb(myKey) { var date2 = new Date(); if ...