java虚拟机jvm启动后java代码层面发生了什么?

0000 我想验证的事情

java代码在被编译后可以被jdk提供的java命令进行加载和运行, 在我们的程序被运行起来的时候,都发生了什么事情, 下面就来探究下这个问题, 这个问题被拆成了两个问题, 第一个问题用来确定发生了哪些事情, 第二个问题用来确定这些事情是如何进行的.

  1. java进程里面都发生了哪些活动?
  2. 这些活动在java代码(反编译或者是源码)级别有所体现吗?

0001 寻找验证的方式

当我在探究上面两个问题时, 我想了很多方式去探究这两个问题,下面是我想到的方法

  1. java官方文档? 没有找到
  2. 搜索引擎? 没有找到
  3. idea中debug? 有点线索

在idea中打上断点然后debug时, 我发现了一个东西,以下是idea中的debug截图

image.png

看到了这个关于线程和调用堆栈的线索, 那么java代码层面中发生了哪些事情就好确定了
通过线程名字可以看出这个线程主要负责的事情.

image.png

0002 确认验证的入口

idea中的debug窗口的线程选择下拉框显示了一些可以进行debug操作的线程, 那么可以断定这几个线程都有对应java代码入口, 我们可以根据这些堆栈的入口来进行代码阅读, 感兴趣的可以看看里面究竟发生了哪些事情
idea中的可debug的线程没有通过jstack命令显示的线程多, 下面是通过jstack命令dump出来的数据:

"RMI TCP Connection(2)-192.168.191.1" #18 daemon prio=5 os_prio=0 tid=0x000000001b409800 nid=0x80a4 runnable [0x000000001c93d000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x00000000d7520cb0> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$Lambda$3/1223273742.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

Locked ownable synchronizers:
- <0x00000000d6c99530> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"JMX server connection timeout 17" #17 daemon prio=5 os_prio=0 tid=0x000000001ae9e000 nid=0x8088 in Object.wait() [0x000000001c63f000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d715f378> (a [I)
at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
- locked <0x00000000d715f378> (a [I)
at java.lang.Thread.run(Thread.java:748)

Locked ownable synchronizers:
- None

"RMI Scheduler(0)" #16 daemon prio=5 os_prio=0 tid=0x000000001b1c6800 nid=0x8084 waiting on condition [0x000000001c53e000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000d69fbee0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

Locked ownable synchronizers:
- None

"RMI TCP Connection(1)-192.168.191.1" #15 daemon prio=5 os_prio=0 tid=0x000000001ae1a800 nid=0x8080 runnable [0x000000001c43d000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x00000000d6ddc2e0> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$3/1223273742.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

Locked ownable synchronizers:
- <0x00000000d6c93ac0> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"RMI TCP Accept-0" #14 daemon prio=5 os_prio=0 tid=0x000000001a833800 nid=0x8074 runnable [0x000000001c23e000]
java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
- locked <0x00000000d6be9bb0> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:405)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377)
at java.lang.Thread.run(Thread.java:748)

Locked ownable synchronizers:
- None

"Service Thread" #12 daemon prio=9 os_prio=0 tid=0x000000001a653800 nid=0x3be8 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C1 CompilerThread2" #11 daemon prio=9 os_prio=2 tid=0x000000001a63f000 nid=0x70b8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C2 CompilerThread1" #10 daemon prio=9 os_prio=2 tid=0x000000001a5ed800 nid=0x7898 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C2 CompilerThread0" #9 daemon prio=9 os_prio=2 tid=0x000000001a5ec800 nid=0x79a4 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"JDWP Command Reader" #8 daemon prio=10 os_prio=0 tid=0x0000000018458800 nid=0x7520 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"JDWP Event Helper Thread" #7 daemon prio=10 os_prio=0 tid=0x0000000018455000 nid=0x7c44 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"JDWP Transport Listener: dt_socket" #6 daemon prio=10 os_prio=0 tid=0x0000000018449000 nid=0x7a50 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000197b3000 nid=0x3250 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001842a800 nid=0x4c8c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000037bd800 nid=0x764c in Object.wait() [0x000000001976f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5d88ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000d5d88ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

Locked ownable synchronizers:
- None

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000037bc000 nid=0x3c8c in Object.wait() [0x000000001966e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5d86bf8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000d5d86bf8> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

Locked ownable synchronizers:
- None

"main" #1 prio=5 os_prio=0 tid=0x00000000036c4000 nid=0x1cb0 runnable [0x00000000035bf000]
java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:255)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x00000000d5de89a8> (a java.io.BufferedInputStream)
at com.TaskTest.main(Test.java:179)

Locked ownable synchronizers:
- None

"VM Thread" os_prio=2 tid=0x00000000183d8000 nid=0x6d38 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000036e2800 nid=0x7e88 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000036e4000 nid=0x35e4 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000036e5800 nid=0x4ed4 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000036e7000 nid=0x702c runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001a69f000 nid=0x2af8 waiting on condition

JNI global references: 5253

可以看出来jstack导出的线程有些有调用堆栈, 有些没有, 是这样的, 没有堆栈的线程应该是jvm的一些核心线程, 这些核心线程提供了jvm的核心功能, 比如垃圾回收, 即时编译等. 带有堆栈的这些线程都是由java代码作为入口构建出来的, 所以我们能根据这些入口去查看里面的具体逻辑, 这些线程中有一个线程main, 这个线程就是为带有main方法入口的java应用构建出来的, 这个线程主要执行动作就是java应用由入口方法所触发的程序逻辑.
带有堆栈信息的这些线程, 在执行其自身代码的逻辑之外, 还会被jvm用于执行类加载这个动作. 如何验证这个类加载的动作呢, 如果你用的idea, 在设置中开启debug时进入类加载器断点, idea默认不开启这个动作, 然后把断点打点到类加载器的loadClass这个方法中, 给出以下具体位置:sun.misc.Launcher.AppClassLoader#loadClass, 如何确定是这个类呢, 大家可以在自己的main方法中获取自己定义的类的类对象, 根据类对象的方法getClassLoader就可以确认类加载器了, 对于AppClassLoader这个类加载器大家肯定不会陌生, 比较有名双亲委派模型就是由这个类实现的, 大家有兴趣的可以去扒下代码, 验证下自己读过的文章是不是和代码一致. 最后以debug模式启动你的main代码, 你就可以命中类加载器中的代码了. 好了, 好好琢磨琢磨这些代码逻辑吧.

下次再见

0003 网络资源

下面是一些本文的相关资源

JVM 内部运行线程介绍
https://www.cnblogs.com/williamjie/p/9389349.html
各个工具如何查找加载类
https://docs.oracle.com/javase/8/docs/technotes/tools/findingclasses.html
java虚拟机如何查找加载类
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容