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

0000 我想验证的事情

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

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

0001 寻找验证的方式

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

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

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

idea调试面板

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

线程名称

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, 这只是咱们项目代码中的定义类型的类加载器.

那如何确定是某个类的类加载器呢, 大家可以在自己的先获取类的类对象, 根据类对象的方法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

java虚拟机jvm启动后java代码层面发生了什么?的更多相关文章

  1. 如何设置Java虚拟机JVM启动内存参数

    Tomcat默认的Java虚拟机JVM启动内存参数大约只有64MB或者128MB,非常小,远远没有利用现在服务器的强大内存,所以要设置Java虚拟机JVM启动内存参数.具体设置方法为: Tomcat修 ...

  2. Java虚拟机JVM内存分区及代码执行机制

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt230 1.  JVM体系结构 图1 JVM体系结构    方法区:存放JVM ...

  3. [java] 虚拟机(JVM)底层结构详解[转]

    本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领域中大部分的知识点,从最基础的java最基本语法到 ...

  4. 深入解析java虚拟机-jvm运行机制

    转自oschina 一:JVM基础概念 JVM(Java虚拟机)一种用于计算设备的规范,可用不同的方式(软件或硬件)加以实现.编译虚拟机的指令集与编译微处理器的指令集非常类似.Java虚拟机包括一套字 ...

  5. Java虚拟机(JVM)默认字符集详解

    Java中对字符串等进行转换字节数组时, 需要根据字符集编码来进行转换, 当不显示的指定字符集编码时(如: "测试".getBytes()), 会使用Charset.default ...

  6. Java基础:Java虚拟机(JVM)

    当我们第一次学习Java时这些原理上的东西就会被提到,但是很少有真正去学习.今天开始从头过一遍Java,打算从JVM开始. 1. JVM是什么 2. JRE和JDK 3. JVM结构 3.1. 程序计 ...

  7. 深入理解JAVA虚拟机JVM

    深入理解JAVA虚拟机JVM Java 虚拟机(Java virtual machine,JVM)是运行 Java 程序必不可少的机制.java之所以能实现一次编写到处执行,也就是因为jVM.原理:编 ...

  8. Java虚拟机(JVM)知多少

    本文大量参考:https://www.cnblogs.com/lfs2640666960/p/9297176.html 概述 JVM是JRE的一部分.它是一个虚构出来的计算机,是通过在实际的计算机上仿 ...

  9. 深入理解java虚拟机JVM(上)

    深入理解java虚拟机JVM(上) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...

随机推荐

  1. win + ubuntu 双系统 grub引导项修复

    ubuntu liveCD模式,找到ubuntu的系统盘位置,挂载到系统上面,然后使用grub进行修复 ubuntu liveCD模式下是用boot-repair软件进行修复 grub急救模式 1. ...

  2. Go的内存对齐和指针运算详解和实践

    uintptr 和 unsafe普及 uintptr 在Go的源码中uintptr的定义如下: /* uintptr is an integer type that is large enough t ...

  3. window 10 安装Oracle odac 64位

    下载地址:https://www.oracle.com/cn/database/technologies/windows/downloads.html 可以下载XCopy版,也可以继续往下看下载安装文 ...

  4. Linux删除文件 清除缓存

    相信很多测试 经常会经历开发叫你清除缓存这种事. 那我们要怎么清呢? 一.首先,确认你要清除的缓存在哪个目录下,然后切换到该目录下,比如 我现在知道我的的缓存目录是在newerp这个目录下,则如图 二 ...

  5. dp-最大连续子序列的和

    https://www.felix021.com/blog/read.php?1587 什么是最大连续子序列和呢 ? 最大连续子序列和是所有子序列中元素和最大的一个 . 问题 : 给定一个序列 { - ...

  6. Java入门 - 高级教程 - 07.多线程

    原文地址:http://www.work100.net/training/java-multi-threading.html 更多教程:光束云 - 免费课程 多线程 序号 文内章节 视频 1 概述 2 ...

  7. [bzoj1045] [洛谷P2512] [HAOI2008] 糖果传递

    Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数nn<=1'000'000,表示小朋友的个 ...

  8. ii

    char a[10], b[10], c[10], d[10],e[10],f[10],g[10],h[10]; scanf("%s %s %s %s", a, b, c, d); ...

  9. linux DNS 服务器 配置

    1:named.conf 2:正向区域配置文件 3:反向域名解析文件

  10. 这个时候 快下班了 我来翻译一段: Pro ASP.NET MVC 3 Framework

    Binding to a Derived Type绑定派生类型Although we have focused on interfaces (since that is most relevant i ...