性能文章>难怪我看不懂!call_stub竟然这么玄乎!>

难怪我看不懂!call_stub竟然这么玄乎!原创

1983234

哈喽,我是子牙。十余年技术生涯,一路披荆斩棘从技术小白到技术总监到JVM专家到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核。特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。

 

手撸过JVM、内存池、垃圾回收算法、synchronized、线程池、NIO…

 

 

最近正在写三色标记算法 ^_^

01

这次聊这个

 

这篇文章想跟大家聊聊Hotspot源码的call_stub,如图

 

 

这啥?这篇文章目前还不适合你,默默关掉吧,我理解的!

 

为什么要聊这个?我又看不懂!(白眼)给我硬看!

 

这个问题是卷Hotspot的小伙伴问得比较多的,每次回答就像顺藤摸瓜一样,小伙伴们顺着我的回答抛出一堆问题,我怕了,写篇文章把讲透吧,后面谁来问,这篇文章丢过去。看不懂?多看几遍!

 

坦白讲,就这么一段代码,涉及到的知识点还真不少:

  1. 函数指针

  2. 变量定义花招

02

铺垫知识

 

先说宏,比较简单,就两个知识点:

  1. 宏定义,通过#define定义

  2. 宏展开,预处理阶段直接替换

 

打个比方

 

 

这是比较简单的,有的宏定义就像函数一样,还传参,把人搞疯了!万变不离其宗,无脑替换就可以了。


接下来谈谈函数指针,这个一两句话讲不清,我就举个例子了

 

 

总结一下:函数指针的强大就在于它可以用来定义函数,这个函数你给它什么地址,它就把那块内存当成函数执行

 

如果这样说你还是不懂,百度一下吧


好,最后一个铺垫知识:花样定义变量

 

 

OK,万事具备,开始卷。

 

顺便提一嘴,我在做手写JVM小班,就是以手写JVM为契机教大家底层如:汇编、C、C++、操作系统…底层最重要的不是视频,而是老师本人在你遇到问题的时候能指点你。如果你想学习底层,想成为技术大牛,来找我。

03

开始卷

 

点开call_stub,是一个函数,长这样,函数体是一个宏

 

static CallStub call_stub() { return CAST_TO_FN_PTR(CallStub, _call_stub_entry); }

 

找到宏定义

 

#define CAST_TO_FN_PTR(func_type, value) ((func_type)(castable_address(value)))

 

手动展开

 

static CallStub call_stub() { 
// return CAST_TO_FN_PTR(CallStub, _call_stub_entry);
    return (CallStub)(castable_address(_call_stub_entry));
}

 

继续展开

 

inline address_word  castable_address(address x)              { return address_word(x) ; }

typedef uintptr_t address_word;

static CallStub call_stub() {
// return CAST_TO_FN_PTR(CallStub, _call_stub_entry);
    // return (CallStub)(castable_address(_call_stub_entry));
return (CallStub)address_word(_call_stub_entry);
}

 

还有一个碍事的CallStub,继续展开

 

// Calls to Java
typedef void (*CallStub)(
address link,
intptr_t* result,
BasicType result_type,
Method* method,
address entry_point,
intptr_t* parameters,
int size_of_parameters,
TRAPS
);

 

最终结果

 

_call_stub_entry(
    (address)&link,
// (intptr_t*)&(result->_value), // see NOTE above (compiler problem)
result_val_address, // see NOTE above (compiler problem)
result_type,
method(),
entry_point,
args->parameters(),
args->size_of_parameters(),
CHECK
);

 

_call_stub_entry是什么?是JVM调用Java函数的那座桥。指向一段内存,这段内存代码在这生成的

 

 

这个函数,加上另外一个:entry_point,是看懂Hotspot运行时的关键。然,这两座大山将99%的人拒之门外。

 

当然,不包括我,我用内联汇编模拟写了一遍

 

 

OK,就到这里,清晰明了。

 

 

 

你好,我是子牙。十余年技术生涯,一路披荆斩棘从小白到技术总监到大厂中间件到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核及特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。不考虑交个朋友吗?关注硬核子牙

 

点赞收藏
分类:标签:
子牙_公号硬核子牙

对编程语言的设计与实现有浓厚兴趣。聚焦Hotspot源码、Linux内核研究,硬核干货分享

请先登录,查看2条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

记一次线上RPC超时故障排查及后续GC调优思路

记一次线上RPC超时故障排查及后续GC调优思路

解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手

解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手

【全网首发】一次疑似 JVM Native 内存泄露的问题分析

【全网首发】一次疑似 JVM Native 内存泄露的问题分析

解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式

解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式

【全网首发】从源码角度分析一次诡异的类被加载问题

【全网首发】从源码角度分析一次诡异的类被加载问题

34
2