对于Java程序来说,JVM是一台完整的机器,可是对于真正的机器或OS来说,JVM只是其中一个进程而已。作为一个进程,它又是如何启动的呢?如下来一步一步分析。(注,本文分析的JDK源代码是openjdk6,下载地址:http://download.java.net/openjdk/jdk6/)
JVM的进程入口是在...\jdk\src\share\bin\java.c。199行。该方法一开始初始化了一系列的指针并判断是否打开debug(通过set _JAVA_LAUNCHER_DEBUG=1打开).接下来就进入了CreateExecutionEnvironment函数,该函数主要作用是查找Java程序的运行目录。那么这个函数在中间到底做了些什么呢? 两件事:
(1)、查找jre路径:这个功能是通过...\jdk\src\
\bin\java_md.c中的GetJREPath函数实现的。首先其通过GetApplicationHome获取到路径,代码如下:
[code="c"]/*
* If app is "c:\foo\bin\javac", then put "c:\foo" into buf.
*/
jboolean
GetApplicationHome(char *buf, jint bufsize)
{
char *cp;
GetModuleFileName(0, buf, bufsize);
*strrchr(buf, '\\') = '\0'; /* remove .exe file name */
if ((cp = strrchr(buf, '\\')) == 0) {
/* This happens if the application is in a drive root, and
* there is no bin directory. */
buf[0] = '\0';
return JNI_FALSE;
}
*cp = '\0'; /* remove the bin\ part */
retur JNI_TRUE;
}
找到ApplicationHome之后,GetJREPath函数会通过如下的方式来确定JREPath。
GetPublicJREHome函数的逻辑就是先查找
HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\CurrentVersion
键值“当前JRE版本号”,然后取HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\“当前JRE版本号”\JavaHome的路径所在 为JRE路径。
小验证:
打开DEBUG,执行java -ersion,得到:
----_JAVA_LAUNCHER_DEBUG----
Version major.minor.micro = 1.6.0
JRE path is E:\Java\jre1.6.0
.............................
执行javac,得到:
----_JAVA_LAUNCHER_DEBUG----
JRE path is E:\Java\jdk1.6.0\jre
..................
这里要思考的是:为什么2者不一样呢??
其实,逻辑还是上面的那一套逻辑,只是忽略的一点是,在我们安装JDK的时候,会拷贝一份java.exe到C:\WINDOWS\system32\下,系统的Path目录包含了该目录,且先于我们配置的JAVA目录,所以,执行java -ersion的时候使用的是Windows目录下的那个java.exe而不是JAVA目录下的,所以导致走的PublicJRE的那个路径。
(2)、获取当前环境需要装载的jvm.dll文件路径:
要获取本机平台上应该使用哪个jvm.dll,是先通过java.c的ReadKnownVMs方法获取当前主机的jvm.cfg.该函数逻辑就是构造“JRE路径+\lib+\ARCH(CPU构架)+\jvm.cfg”路径。(ARCH的值是通过java_md.c的GetArch实现的。)
[code="c"]GetArch()
{
#ifdef _M_AMD64
return "amd64";
#elif defined(_M_IA64)
return "ia64";
#else
return "i386";
#endif
}
jvm.cfg文件的格式如下:
#
# @(#)jvm.cfg 1.8 05/11/17
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
#
#
#
#
# List of JVMs that can be used as an option to java, javac, etc.
# Order is important -- first in this list is the default JVM.
# NOTE that this both this file and its format are UNSUPPORTED and
# WILL GO AWAY in a future release.
#
# You may also select a JVM in an arbitrary location with the
# "-XXaltjvm=" option, but that too is unsupported
# and may not be available in a future release.
#
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
ReadKnownVMs函数会将该文件中的配置内容读入到一个JVM配置结构的全局变量中,该函数首先跳过注释(以‘#’开始的行),然后读取以‘-’开始的行指定的jvm参数,每一行为一个jvm信息,第一部分为jvm虚拟机名称,第二部分为配置参数,比如行:“-client KNOWN”则“-client”为虚拟机名称,而“KNOWN”为配置类型参数,“KNOWN”表示该虚拟机的jvm.dll存在,而“ALIASED_TO”表示为另一个jvm.dll的别名,“WARN”表示该虚拟机的jvm.dll不存在但运行时会用其他存在的jvm.dll替代执行,而“ERROR”同样表示该类虚拟机的jvm.dll不存在且运行时不会找存在的jvm.dll替代而直接抛出错误信息。
加载完jvm.cfg文件之后,java.c会调用CheckJvmType方法去检测本机应该使用哪一个类型的JVM。该方法会首先判断用户是否有指定JVM类型,如果有就从前加载的jvm.cfg的数据中查找是否有用户指定的类型。如果用户指定的类型不合法,会抛异常。如果用户没有指定JVM类型,则直接返回jvm.cfg的第一项。
用户可以通过4种方式指定jvm的类型,“按照jvm.cfg文件中的jvm名称指定”,“java -J”、“java -XXaltjvm=”和“java -J-XXaltjvm=”。
获取到JVM的类型之后,进程会通过java_md.c的GetJVMPath的方法,把前面获取的JREPath,JVMType一起组成jvm.dll的绝对路径“JRE路径+\bin+\jvm类型字符串+\jvm.dll”。
以上是我个人学习总结所得,可能会有很多理解偏颇之处,欢迎指正探讨,也让我不要在错误的道路上越走越远,谢谢,龙年吉祥。
参考文章:http://zhidao.baidu.com/question/5956019
http://blog.163.com/irene_lwx@126/blog/static/28064560200792864055915/
- 大小: 20.4 KB
分享到:
相关推荐
openjdk8源码,适合深入学习jdk源码的同学
除此之外,OpenJDK源码还包含了丰富的工具集,如javac编译器、jdb调试器、jmap内存分析工具等。这些工具的源码可以帮助开发者了解如何构建和维护复杂的系统工具,同时也可以提升他们对Java平台整体工作流程的理解。 ...
《OpenJDK源码探索——基于openjdk-7u4-fcs-src-b22-02_may_2012》 OpenJDK,全称为Open Source Java Development Kit,是Java开发工具集的一个开源实现,它为Java平台提供了一个开放源代码的实现,包括HotSpot...
OpenJDK(Open Java Development Kit)是Java开发工具包的一个开源实现,它是Oracle JDK的开源版本,...通过深入研究OpenJDK源码,开发者不仅可以提升自己的Java技术能力,还可以为社区贡献代码,推动Java技术的发展。
1. 类加载器:Java的类加载机制是双亲委派模型,OpenJDK源码揭示了如何查找并加载类,以及如何处理类的加载、链接和初始化过程。 2. 内存管理:JVM的内存结构包括堆、栈、方法区等,OpenJDK的源码中详细描述了对象...
《OpenJDK源码分析——探索Java开发的底层奥秘》 OpenJDK,全称为Open Source Java Development Kit,是Java开发工具集的开源版本,它提供了Java平台标准版(Java SE)的实现。深入理解OpenJDK源码,对于Java开发者...
OpenJDK Hotspot源码是Java开发者深入理解Java虚拟机(JVM)工作原理的关键资源。Hotspot JVM是Oracle公司开发的开源Java虚拟机实现,它以高效的性能优化著称,包括即时编译(JIT)和动态优化。在深入探讨Hotspot...
OpenJDK源码是理解Java虚拟机(JVM)、类库以及Java语言实现的关键资源,对于开发者来说具有极高的学习价值。下面我们将深入探讨OpenJDK源码中的关键知识点。 1. **HotSpot虚拟机**:OpenJDK的核心部分是HotSpot...
源码分析可以帮助我们深入了解Java虚拟机(JVM)的工作原理、类库的实现细节以及垃圾回收机制等核心内容。 1. **JVM架构与执行引擎** - **字节码解析器**: OpenJDK8使用C1(Client Compiler)和C2(Server ...
3. **源码分析**: 查看rt.jar的源码对于学习Java语言的底层实现非常有帮助。例如,可以研究`Object`类的`clone()`方法是如何工作的,或者`ArrayList`如何实现动态扩容。通过Eclipse等IDE查看源码,可以设置断点,...
在Java世界中,源码分析是提升技术能力的重要途径,尤其对于OpenJDK这种基础性软件,其源码更是开发者探索Java运行机制的金钥匙。OpenJDK 7U源码不仅包括了JVM的实现,还涵盖了类库和编译器等多个重要组件,这些组件...
通过研究OpenJDK7的源码,开发者可以了解Java语言的底层实现,学习如何优化JVM参数,以及如何针对特定场景调整Hotspot的编译和垃圾回收策略。这对于理解Java程序的性能瓶颈,提升软件的运行效率具有极大的帮助。 ...
《OpenJDK源码探索——深入理解Java运行机制》 OpenJDK,全称为Open Source Java Development Kit,是Java开发工具集的一个开源实现,由Oracle公司主导并维护,旨在为Java开发者提供一个开放、免费的平台来研究和...
1. **JEPs(Java Enhancement Proposals)**:OpenJDK9的开发过程由一系列的JEPs驱动,这些提案定义了新功能和改进。例如,JEP 222(HTTP Client (Standard)**引入了一个新的标准HTTP客户端API,替代了老旧的`java...
理解OpenJDK源码需要扎实的Java基础和一定的底层知识。可以从以下几个步骤入手: 1. 熟悉JVM基本原理:理解类加载、内存模型、垃圾收集等概念。 2. 阅读JDK库源码:了解常用API的实现细节,如Collections、...
开发者可以通过分析这些源码,理解Java的内存管理、线程调度、字节码解释和优化等核心机制。例如,`src/hotspot`目录下的源码涉及了虚拟机的实现,包括解析和执行字节码的解释器、即时编译器以及内存管理系统等。 ...
OpenJDK的源码分析可以帮助我们深入理解Java程序的运行机制,包括内存管理、垃圾回收、线程模型、编译与解释器的工作原理等。 1. JVM基本认识 Java虚拟机(JVM)是Java运行时环境的核心,它负责执行Java字节码。...
1. javac编译器:javac的源码揭示了Java语言的编译过程。它首先通过词法分析和语法分析将源代码转化为抽象语法树(Abstract Syntax Tree, AST),然后进行类型检查和语义分析,最后生成对应的字节码。在这个过程中,...
OpenJDK 1.7源码是Java开发领域的重要参考资料,它揭示了Java平台的核心运行机制,对于开发者来说,理解和研究OpenJDK源码有助于提升编程技能,优化代码性能,以及解决实际问题。src.zip文件包含了OpenJDK 1.7的所有...
8. **内存模型和并发**:OpenJDK源码揭示了Java内存模型(JMM)的实现,以及如何在多线程环境中确保数据一致性。你可以看到`synchronized`关键字、`volatile`变量、`Atomic`类等并发控制机制的内部实现。 通过对...