39

在 Java 虚拟机上班是一种怎样的体验?

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA%3D%3D&%3Bmid=2650755246&%3Bidx=3&%3Bsn=9f3ead226cf9e7b0da82b12b03a6db35
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

FZZZRzY.gif

YbAZryB.png!web

来源 |  编程技术宇宙

责编| Carol

封图 | CSDN 下载自视觉中国

本文用知乎体的风格简单介绍了JVM中几个内置线程的工作,希望对大家学习JVM有一点帮助。

mmA7326.jpg!web

匿名用户

JVM老鸟

228 人赞同了该回答

利益相 关,匿了!

JVM公司里面线程众多,派系林立,尤其是执行引擎那波人,因为是核心部门,经常diss别的部门。

jqaMN3f.jpg!web

FinalizerThread

JVM核心员工,GC部门高级工程师。

428 人赞同了该回答

不请自来。

其实在JVM工作没有你们想象的那么辛苦,其他部门不清楚,就拿我所在的垃圾回收部(这名字不好听,叫GC部门吧)来说说。

我的工作是负责执行对象的 finalize 方法,你们也知道,现在的程序员,很少实现类的这个方法了,所以我的工作大部分时间都可以摸鱼。

评论里有人问我对象的 finalize 方法是如何被执行的,这里统一回复一下。

JVM的 ClassLoader 部门在加载一个class的时候,会检查它是否有实现 finalize 方法,具体细节我不太清楚,请  @AppClassLoader 同学来帮忙解答一下。

如果发现有 finalize 方法,以后创建这个类的所有对象都会附带创建一个 Finalizer 对象。

这个 Finalizer 有两个关键点:

  • 继承自Reference类,本身也是一个引用,引用的正是跟它一起创建的那个对象

  • 里面有一个名叫queue的成员,指向了一个队列: ReferenceQueue ,正是 Finalizer 的一个静态成员变量。
ZNfiqqI.png!web

除此之外, Finalizer 里面还有一个静态线程 FinalizerThread ,这个其实就是我了。我的工作就是不断上面的队列里面取出 Finalizer 对象,然后执行它引用对象的 finalize 方法。

什么?你问我 Finalizer 对象是什么时候进入这个队列里的?这我就不知道了,超出了我的工作范围,可以请  @ReferenceHandler 帮忙解答一下。

以上。

ZfY7neb.jpg!web

AppClassLoader

JVM核心员工,类加载部门工程师。

522 人赞同了该回答

邀!

JVM公司整体来说还是挺不错的,各方面条件都还不错。办公大厦有两层,一楼是native层,一堆native层的线程员工在下面办公。我在二楼的Java层,这一层都是Java线程。

我在JVM类加载部门工作,我的Leader是 ExtClassLoader ,他的Leader是公司高管 BootstrapClassLoader

我们部门的工作就是把磁盘上的.class文件加载到内存中,变成一个个可以使用的类。工作嘛还算轻松。不过有一点让我不爽的是部门的 双亲委派 制度。

MrUBFnV.png!web

每次遇到新的类需要加载,按照规定都必须请示领导来加载,领导又去请示他的领导来加载。但是高管 BootstrapClassLoader 只负责加载Java的核心类,我的领导也只负责加载一些扩展类,所以大部分时间请示完了结果他们都加载不了,还得让我去加载。

一来二去的花了不少时间在流程上,瞎耽误工夫。我多次反应这个问题,能不能不请示我直接加载算了,不过每次都被驳回,说是为了安全考虑,他们必须过目。唉,领导不肯放权也是难办!

------------分割线------------

评论区戾气太重!说我不懂安全也是醉了。

回答一下 @FinalizerThread 同学的问题。

确实如他所说,我们ClassLoader会去检查类有没有实现 finalize 方法,检查结果会保存在 Klass 结构中的 AccessFlags 里。

这是一个很重要的字段,记录了类的很多属性:

uyEze2n.png!web

有了这些信息,创建对象的时候就可以检查标记来决定是否创建 Finalizer 对象了。

以上。

vmMNjez.png!web

ReferenceHandler

JVM核心员工,GC部门高级工程师。

145 人赞同了该回答

感谢  @FinalizerThread  同学邀请。

人在JVM,刚下晚班。

时间紧迫,简单说几句。

和这位同学一样,我也是GC部门的员工,公司待遇确实不错,这方面还是很有竞争力的。

至于我的工作嘛,跟垃圾回收密切相关!

你们也知道在Java中,除了基础的强引用外,还有四种特殊的引用:

  • FinalReference

  • 软引用(SoftReference)

  • 弱引用(WeakReference)

  • 虚引用(PhantomReference)

前面FinalizerThread同学提到的Finalizer其实就是FinalReference的子类。

我的工作就是在垃圾回收时,把这些个特殊引用一个个加入到它们各自对应的队列里面去。

拿上面FinalizerThread同学提到的Finalizer对象来说,就是我来把它加到它所指向的队列中,再由FinalizerThread同学去从这个队列里面取出来处理的。

2ueiMjB.jpg!web

VMThread

JVM核心员工,后勤部主管。

898 人赞同了该回答

这个问题我来简单回答一下。

看了前面几位的回答,真的是旱的旱死,涝的涝死。我一天天忙得气都喘不过来,你们居然还有时间摸鱼!

我算是JVM公司里每天到的最早的几个了,跟随 Threads::create_vm 就起来了。

和楼上两位一样的是我也有一个工作队列,叫_vm_thread,其类型是 VMOperationQueue

和楼上两位不一样的是他们工作在二楼Java层,而我工作在一楼native层。

工作节奏这个东西真的是不同部门差得很远,我所在的部门就我一个人,是一个单例线程,我要干的就是不断从工作队列里面取出操作来执行。

这个队列里面装的都是一个个封装成 VM_Operation 的东西,这是它们的基类,具体来说,有几十种操作,列举一部分,你们随意感受一下:

#define VM_OPS_DO(template)                       \
template(None) \
template(ThreadStop) \
template(ThreadDump) \
template(PrintThreads) \
template(FindDeadlocks) \
template(ClearICs) \
template(ForceSafepoint) \
template(ForceAsyncSafepoint) \
template(Deoptimize) \
template(DeoptimizeFrame) \
template(DeoptimizeAll) \
template(ZombieAll) \
template(Verify) \
template(PrintJNI) \
template(HeapDumper) \
template(DeoptimizeTheWorld) \
template(CollectForMetadataAllocation) \
template(GC_HeapInspection) \
template(GenCollectFull) \
template(GenCollectFullConcurrent) \
template(GenCollectForAllocation) \
template(ParallelGCFailedAllocation) \
template(ParallelGCSystemGC) \
······

其他就不说了,就拿你们最熟悉的垃圾回收来说,没有了我,JVM的堆区内存恐怕早就垃圾堆成山了。

时间关系,先写到这里。

--------- ---- --分割线------ --- ------

一觉醒来居然有这么多赞,谢谢大家!

再补充几句。

VM_Operation 中还设置了一个模式,用来表示执行这个操作是否需要进入安全点,(比如垃圾回收就需要),是否需要加锁执行。

  enum Mode {
_safepoint, // blocking, safepoint
_no_safepoint, // blocking, no safepoint
_concurrent, // non-blocking, no safepoint
_async_safepoint // non-blocking, safepoint
};

安全点的进入和退出都是我来发起的,执行的是 SafepointSynchronizebegin()函数end() 函数。

以上。

y6VvAn6.png!web

更多精彩推荐

更多精彩推荐

国士无双:卖掉美国房子,回国创办姚班,他只为培养一流的程序员!

☞对话 SmartX:领跑超融合中高端市场之道——用专注加专业构筑企业云基础

过分了!耗资 5600 万、4 年开发的网络商城成“烂尾楼”,404 无法打开

知道路由器工作原理?没关系,来这看看!看不懂你捶我 | 原力计划

万字长文带你入门 GCN

你点的每个“在看”,我都认真当成了喜欢


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK