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. 关于java php go 中AES加解密秘钥长度问题

    今天心血来朝,想用go把php中的一个小功能重写一下,但在解密aes加密的数据时碰到了个坑! php的mcrypt拓展(貌似php7.1版本以上不支持了)提供了aes的加解密: 而且php aes 的 ...

  2. 关于爬虫的日常复习(7)—— DOM操作及selenium库

  3. 异数OS谈发展国产操作系统的问题

    异数OS谈发展国产操作系统的问题 为什么写本文 最近中兴被美制裁的问题以及红芯使用开源技术宣称国产自主技术引发了舆论不少对国产CPU以及国产操作系统自主技术的讨论,为什么我们国家有BAT,有原子弹,能 ...

  4. (转) exp1-1:// 一次有趣的XSS漏洞挖掘分析(1)

    from http://www.cnblogs.com/hookjoy/p/3503786.html 一次有趣的XSS漏洞挖掘分析(1)   最近认识了个新朋友,天天找我搞XSS.搞了三天,感觉这一套 ...

  5. 实验三:在eNSP上进行Hybrid链路类型端口实验

    1.配置图 2.配置命令 LSW1的命令配置如下: <Huawei>system-view 进入特权模式 [Huawei]vlan batch 2 3 99 创建vlan2.vlan3.v ...

  6. nginx之文件配置

    nginx配置规则 nginx由受配置文件中指定的指令控制的模块组成 伪指令分为简单伪指令和块伪指令 简单的指令由名称和参数组成,这些名称和参数之间用空格分隔,并以分号(;)结尾 块指令的结构 与 简 ...

  7. (转)Gamma分布,Beta分布,Multinomial多项式分布,Dirichlet狄利克雷分布

    1. Gamma函数 首先我们可以看一下Gamma函数的定义: Gamma的重要性质包括下面几条: 1. 递推公式: 2. 对于正整数n, 有 因此可以说Gamma函数是阶乘的推广. 3.  4.  ...

  8. C++快读模板

    C++的快速读入模板 inline int read() { ; char ch = getchar(); ') { if (ch == '-') flag = true; ch = getchar( ...

  9. Mavn 项目 引入第三方jar包 导致ClassNotFoundException

    案例 我有一个Maven构建的项目,项目模块之间有依赖关系,我需要用到一个本地的jar包,而该jar包不能通过配置pom.xml文件从远程仓库自动下载,于是我直接导入该jar包到其中一个项目,不通过p ...

  10. SVN: 聚合工程下的子工程无法使用 svn:ignore

    当想将聚合工程manager下子工程没用的一些文件使用svn:ignore,发现该功能不能使用 这是因为SVN 服务器上还没有这些子工程的文件夹,只有聚合工程的文件夹,所以SVN认为在服务器上这些代码 ...