java虚拟机jvm启动后java代码层面发生了什么?
java虚拟机jvm启动后java代码层面发生了什么?
java代码在被编译后可以被jdk提供的java命令进行加载和运行, 在我们的程序被运行起来的时候,都发生了什么事情, 下面就来探究下这个问题, 这个问题被拆成了两个问题, 第一个问题用来确定发生了哪些事情, 第二个问题用来确定这些事情是如何进行的.
- java进程里面都发生了哪些活动?
- 这些活动在java代码(反编译或者是源码)级别有所体现吗?
0001 寻找验证的方式
当我在探究上面两个问题时, 我想了很多方式去探究这两个问题,下面是我想到的方法
- java官方文档? 没有找到
- 搜索引擎? 没有找到
- 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: RUNNABLELocked ownable synchronizers:
- None"C1 CompilerThread2" #11 daemon prio=9 os_prio=2 tid=0x000000001a63f000 nid=0x70b8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLELocked ownable synchronizers:
- None"C2 CompilerThread1" #10 daemon prio=9 os_prio=2 tid=0x000000001a5ed800 nid=0x7898 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLELocked ownable synchronizers:
- None"C2 CompilerThread0" #9 daemon prio=9 os_prio=2 tid=0x000000001a5ec800 nid=0x79a4 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLELocked ownable synchronizers:
- None"JDWP Command Reader" #8 daemon prio=10 os_prio=0 tid=0x0000000018458800 nid=0x7520 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLELocked ownable synchronizers:
- None"JDWP Event Helper Thread" #7 daemon prio=10 os_prio=0 tid=0x0000000018455000 nid=0x7c44 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLELocked 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: RUNNABLELocked ownable synchronizers:
- None"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000197b3000 nid=0x3250 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLELocked ownable synchronizers:
- None"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001842a800 nid=0x4c8c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLELocked 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代码层面发生了什么?的更多相关文章
- 如何设置Java虚拟机JVM启动内存参数
Tomcat默认的Java虚拟机JVM启动内存参数大约只有64MB或者128MB,非常小,远远没有利用现在服务器的强大内存,所以要设置Java虚拟机JVM启动内存参数.具体设置方法为: Tomcat修 ...
- Java虚拟机JVM内存分区及代码执行机制
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt230 1. JVM体系结构 图1 JVM体系结构 方法区:存放JVM ...
- [java] 虚拟机(JVM)底层结构详解[转]
本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领域中大部分的知识点,从最基础的java最基本语法到 ...
- 深入解析java虚拟机-jvm运行机制
转自oschina 一:JVM基础概念 JVM(Java虚拟机)一种用于计算设备的规范,可用不同的方式(软件或硬件)加以实现.编译虚拟机的指令集与编译微处理器的指令集非常类似.Java虚拟机包括一套字 ...
- Java虚拟机(JVM)默认字符集详解
Java中对字符串等进行转换字节数组时, 需要根据字符集编码来进行转换, 当不显示的指定字符集编码时(如: "测试".getBytes()), 会使用Charset.default ...
- Java基础:Java虚拟机(JVM)
当我们第一次学习Java时这些原理上的东西就会被提到,但是很少有真正去学习.今天开始从头过一遍Java,打算从JVM开始. 1. JVM是什么 2. JRE和JDK 3. JVM结构 3.1. 程序计 ...
- 深入理解JAVA虚拟机JVM
深入理解JAVA虚拟机JVM Java 虚拟机(Java virtual machine,JVM)是运行 Java 程序必不可少的机制.java之所以能实现一次编写到处执行,也就是因为jVM.原理:编 ...
- Java虚拟机(JVM)知多少
本文大量参考:https://www.cnblogs.com/lfs2640666960/p/9297176.html 概述 JVM是JRE的一部分.它是一个虚构出来的计算机,是通过在实际的计算机上仿 ...
- 深入理解java虚拟机JVM(上)
深入理解java虚拟机JVM(上) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...
随机推荐
- # 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- Beetlex实现完整的HTTP协议
在传统网络服务中扩展中需要处理Bytes来进行协议的读写,这种原始的处理方式让工作变得相当繁琐复杂,出错和调试的工作量都非常大:组件为了解决这一问题引用Stream读写方式,这种方式可以极大的简化网络 ...
- Kafka日志压缩剖析
1.概述 最近有些同学在学习Kafka时,问到Kafka的日志压缩(Log Compaction)问题,对于Kafka的日志压缩有些疑惑,今天笔者就为大家来剖析一下Kafka的日志压缩的相关内容. 2 ...
- dp - LIS
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于 ...
- .NET绘制旋转太极图
.NET绘制旋转太极图 我之前发了一篇<用.NET写"算命"程序>的文章,但有人纷纷提出了质疑,认为没有"科学"(mi xin)依据
- 一起来学习XPATH,来看看除了正则表达式我们还能怎么抓取数据
参考学习的网站链接http://www.w3school.com.cn/xpath/xpath_intro.asp 首先理清楚一些常识 以此为例 <?xml version="1.0& ...
- Java框架之MyBatis 06-全局配置-mapper映射-分步查询
MyBatis MyBatis是Apache的一个开源项目iBatis, iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架. iBatis 提供的持 ...
- 启动Ubuntu的时候出现黑屏的情况
在启动Ubuntu的时候出现黑屏的情况,是因为升级了内核导致显卡不兼容,启动的时候应该告诉内核不要加载显卡: 在进入系统选择时按e进入编辑 在quiet splash 后面添加 nomodeset 再 ...
- C语言入门:一维数组的概要
数组的概念: 具有相同数据的有序集合 一维数组的定义格式: int a[5]; 类型说明符 数组名(标识符)[常量表达式(长度)]; 一维数组下标 : 数组的下标 从0开始 最大下标值 为 数组的 ...
- C++ 对TXT 的串并行读写
任务说明:有36篇文档,现在要读入,并统计词频,字典长度25,希望能够比较串并行读写操作的时间差距. 串行读入并统计词频 // LoadDocsInUbuntu.cpp // #include < ...