java源代码分析----jvm.dll装载过程

简述
众所周知java.exe是java
class文件的执行程序,但实际上java.exe程序只是
一个执行的外壳,它会装载jvm.dll(windows下,以下皆以windows平台为例,
linux下和solaris下其实类似,为:libjvm.so),这个动态连接库才是java
虚拟机的实际操作处理所在。本文探究java.exe程序是如何查找和装载jvm.dll
动态库,并调用它进行class文件执行处理的。

源代码
本文分析之代码,《JavaTM
2 SDK, Standard Edition, v1.4.2 fcs
Community Source
Release》,可从sun官方网站下载,主要分析的源代码为:
j2se/src/share/bin/java.c
j2se/src/windows/bin/java_md.c

java.c是什么东西
‘java程序’源代码
所谓‘java程序’,包括jdk中的java.exe/javac.exe/javadoc.exe,java.c源
代码中通过JAVA_ARGS宏来控制生成的代码,如果该宏没定义则编译文件控制生
成java.exe否则编译文件控制生成其他的‘java程序’。
比如:
j2se/make/java/javac/Makefile(这是javac编译文件)中:
$(CD)
../../sun/javac ; $(MAKE) [email protected] RELEASE=$(RELEASE)
FULL_VERSION=$(FULL_VERSION)
j2se/make/sun/javac/javac/Makefile(由上面Makefile文件调用)中:
JAVA_ARGS
= "{ /"-J-ms8m/", /"com.sun.tools.javac.Main/"
}"
则由同一份java.c代码生成的javac.exe程序就会直接调用java类方法:
com.sun.tools.javac.Main,这样使其执行起来就像是直接运行的一个exe文件,
而未定义JAVA_ARGS的java.exe程序则会调用传递过来参数中的类方法。

java.cmain入口函数说起
main()函数中前面一段为重新分配参数指针的处理。
然后调用函数:CreateExecutionEnvironment,该函数主要查找java运行环境的
目录,和jvm.dll这个虚拟机核心动态连接库文件路径所在。根据操作系统不同,
该函数有不同实现版本,但大体处理逻辑相同,我们看看windows平台该函数的处
理(j2se/src/windows/bin/java_md.c)。

CreateExecutionEnvironment函数主要分为三步处理:
a、查找jre路径。
b、装载jvm.cfg中指定的虚拟机动态连接库(jvm.dll)参数。
c、取jvm.dll文件路径。

实现:
a、查找jre路径是通过java_md.c中函数:GetJREPath实现的。
该函数首先调用GetApplicationHome函数,GetApplicationHome函数调用windows
API函数GetModuleFileName取java.exe程序的绝对路径,以我的jdk安装路径为例,
为:“D:/java/j2sdk1.4.2_04/bin/java.exe”,然后去掉文件名取绝对路径为:
“D:/java/j2sdk1.4.2_04/bin”,之后会在去掉最后一级目录,现在绝对路径为:
“D:/java/j2sdk1.4.2_04”。
然后GetJREPath函数继续判断刚刚取的路径+/bin/java.dll组合成的这个java.dll
文件是否存在,如果存在则“D:/java/j2sdk1.4.2_04”为JRE路径,否则判断取得
的“D:/java/j2sdk1.4.2_04”路径+/jre/bin/java.dll文件是否存在,存在则
“D:/java/j2sdk1.4.2_04/jre”为JRE路径。如果上面两种情况都不存在,则从注
册表中去查找(参见函数GetPublicJREHome)。

函数:GetPublicJREHome先查找
HKEY_LOCAL_MACHINE/Software/JavaSoft/Java
Runtime
Environment/CurrentVersion
键值“当前JRE版本号”,判断“当前JRE版本号”是否为1.4做为版本号,如果是则
取HKEY_LOCAL_MACHINE/Software/JavaSoft/Java
Runtime
Environment/“当前JRE版本号”
/JavaHome的路径所在为JRE路径。

我的JDK返回的JRE路径为:“D:/java/j2sdk1.4.2_04/jre”。

b、装载jvm.cfg虚拟机动态连接库配置文件是通过java.c中函数:ReadKnownVMs实现
的。
该函数首先组合jvm.cfg文件的绝对路径,JRE路径+/lib+/ARCH(CPU构架)+/jvm.cfg
ARCH(CPU构架)的判断是通过java_md.c中GetArch函数判断的,该函数中windows平
台只有两种情况:WIN64的‘ia64’,其他情况都为‘i386’。我的为i386所以jvm.cfg
文件绝对路径为:“D:/java/j2sdk1.4.2_04/jre/lib/i386/jvm.cfg”。文件内容如
下:

#
#
@(#)jvm.cfg        1.7
03/01/23

# Copyright 2003 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=<jvm_dir>" 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

(如果细心的话,我们会发现在JDK目录中我的为:“D:/java/j2sdk1.4.2_04/jre/bin/client”和“D:/java/j2sdk1.4.2_04/jre/bin/server”两个目录下都存在jvm.dll文件。而java正是通过jvm.cfg配置文件来管理这些不同版本的jvm.dll的。)

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替代而直接抛出错误
信息。

在运行java程序时指定使用那个虚拟机的判断是由java.c中函数:CheckJvmType判断,该函数会检查java运行参数中是否有指定jvm的参数,然后从ReadKnownVMs函数读取的jvm.cfg数据结构中去查找,从而指定不同的jvm类型(最终导致装载不同jvm.dll)。有两种方法可以指定jvm类型,一种按照jvm.cfg文件中的jvm名称指定,第二种方法是直接指定,它们执行的方法分别是“java
-J<jvm.cfg中jvm名称>”、“java -XXaltjvm=<jvm类型名称>”或“java
-J-XXaltjvm=<jvm类型名称>”。如果是第一种参数传递方式,CheckJvmType函数会取参数‘-J’后面的jvm名称,然后从已知的jvm配置参数中查找如果找到同名的则去掉该jvm名称前的‘-’直接返回该值;而第二种方法,会直接返回“-XXaltjvm=”或“-J-XXaltjvm=”后面的jvm类型名称;如果在运行java时未指定上面两种方法中的任一一种参数,CheckJvmType会取配置文件中第一个配置中的jvm名称,去掉名称前面的‘-’返回该值。CheckJvmType函数的这个返回值会在下面的函数中汇同jre路径组合成jvm.dll的绝对路径。

比如:如果在运行java程序时使用“java
-J-client
test”则ReadKnownVMs会读取参数“-client”然后查找jvm.cfg读入的参数中是否有jvm名称为“-client”的,如果有则去掉jvm名称前的“-”直接返回“client”;而如果在运行java程序时使用如下参数:
“java
-XXaltjvm=D:/java/j2sdk1.4.2_04/jre/bin/client
test”,则ReadKnownVMs
会直接返回“D:/java/j2sdk1.4.2_04/jre/bin/client”;如果不带上面参数执行如:
“java
test”,因为在jvm.cfg配置文件中第一个存在的jvm为“-client”,所以函数
ReadKnownVMs也会去掉jvm名称前的“-”返回“client”。其实这三中情况都是使用的
“D:/java/j2sdk1.4.2_04/jre/bin/client/jvm.dll”这个jvm动态连接库处理test这个class的,见下面GetJVMPath函数。

c、取jvm.dll文件路径是通过java_md.c中函数:GetJVMPath实现的。
由上面两步我们已经获得了JRE路径和jvm的类型字符串。GetJVMPath函数判断CheckJvmType
返回的jvm类型字符串中是否包含了‘/’或‘/’如果包含则以该jvm类型字符串+/jvm.dll作为JVM的全路径,否则以JRE路径+/bin+/jvm类型字符串+/jvm.dll作为JVM的全路径。

看看上面的例子,第一种情况“java
-J-client
test”jvm.dll路径为:
JRE路径+/bin+/jvm类型字符串+/jvm.dll 按照我的JDK路径则为:
“D:/java/j2sdk1.4.2_04/jre”+“/bin”+“/client”+“/jvm.dll”。
第二种情况“java
-XXaltjvm=D:/java/j2sdk1.4.2_04/jre/bin/client
test”路径为:
jvm类型字符串+/jvm.dll即为:“D:/java/j2sdk1.4.2_04/jre/bin/client”+“/jvm.dll”
第三种情况“java
test”为:“D:/java/j2sdk1.4.2_04/jre”+“/bin”+“/client”
+“/jvm.dll”与情况一相同。所以这三种情况都是调用的jvm动态连接库“D:/java/
j2sdk1.4.2_04/jre/bin/client/jvm.dll”处理test类的。

我们来进一步验证一下:
打开cmd控制台:

设置java装载调试
E:/work/java_research>set
_JAVA_LAUNCHER_DEBUG=1
情况一
E:/work/java_research>java -J-client
test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is
D:/java/j2sdk1.4.2_04/jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] =
->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] =
->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] =
->-green<-
299 micro seconds to parse jvm.cfg
JVM path is
D:/java/j2sdk1.4.2_04/jre/bin/client/jvm.dll
2897 micro seconds to
LoadJavaVM
JavaVM args:
    version 0x00010002,
ignoreUnrecognized is JNI_FALSE, nOptions is
2
    option[ 0] =
‘-Djava.class.path=.‘
    option[ 1] =
‘-Dsun.java.command=test.ScanDirectory‘
50001 micro seconds to
InitializeJVM
Main-Class is ‘test.ScanDirectory‘
Apps‘ argc is 0
10208
micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java
test.ScanDirectory DIR [output file]
情况二
E:/work/java_research>java
-XXaltjvm=D:/java/j2sdk1.4.2_04/jre/bin/client
test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is
D:/java/j2sdk1.4.2_04/jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] =
->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] =
->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] =
->-green<-
386 micro seconds to parse jvm.cfg
JVM path is
D:/java/j2sdk1.4.2_04/jre/bin/client/jvm.dll
2795 micro seconds to
LoadJavaVM
JavaVM args:
    version 0x00010002,
ignoreUnrecognized is JNI_FALSE, nOptions is
2
    option[ 0] =
‘-Djava.class.path=.‘
    option[ 1] =
‘-Dsun.java.command=test.ScanDirectory‘
49978 micro seconds to
InitializeJVM
Main-Class is ‘test.ScanDirectory‘
Apps‘ argc is 0
9598
micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java
test.ScanDirectory DIR [output file]
情况三
E:/work/java_research>java
test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is
D:/java/j2sdk1.4.2_04/jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] =
->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] =
->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] =
->-green<-
381 micro seconds to parse jvm.cfg
JVM path is
D:/java/j2sdk1.4.2_04/jre/bin/client/jvm.dll
3038 micro seconds to
LoadJavaVM
JavaVM args:
    version 0x00010002,
ignoreUnrecognized is JNI_FALSE, nOptions is
2
    option[ 0] =
‘-Djava.class.path=.‘
    option[ 1] =
‘-Dsun.java.command=test.ScanDirectory‘
50080 micro seconds to
InitializeJVM
Main-Class is ‘test.ScanDirectory‘
Apps‘ argc is 0
10215
micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java
test.ScanDirectory DIR [output file]
三个的JVM路径都为:
JVM path is
D:/java/j2sdk1.4.2_04/jre/bin/client/jvm.dll

其他情况
E:/work/java_research>java
-J-server test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is
D:/java/j2sdk1.4.2_04/jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] =
->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] =
->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] =
->-green<-
377 micro seconds to parse jvm.cfg
JVM path is
D:/java/j2sdk1.4.2_04/jre/bin/server/jvm.dll
2985 micro seconds to
LoadJavaVM
JavaVM args:
    version 0x00010002,
ignoreUnrecognized is JNI_FALSE, nOptions is
2
    option[ 0] =
‘-Djava.class.path=.‘
    option[ 1] =
‘-Dsun.java.command=test.ScanDirectory‘
62382 micro seconds to
InitializeJVM
Main-Class is ‘test.ScanDirectory‘
Apps‘ argc is 0
12413
micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java
test.ScanDirectory DIR [output file]
E:/work/java_research>java
-XXaltjvm=D:/java/j2sdk1.4.2_04/jre/bin/server
test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is
D:/java/j2sdk1.4.2_04/jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] =
->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] =
->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] =
->-green<-
376 micro seconds to parse jvm.cfg
JVM path is
D:/java/j2sdk1.4.2_04/jre/bin/server/jvm.dll
2937 micro seconds to
LoadJavaVM
JavaVM args:
    version 0x00010002,
ignoreUnrecognized is JNI_FALSE, nOptions is
2
    option[ 0] =
‘-Djava.class.path=.‘
    option[ 1] =
‘-Dsun.java.command=test.ScanDirectory‘
62725 micro seconds to
InitializeJVM
Main-Class is ‘test.ScanDirectory‘
Apps‘ argc is 0
8942
micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java
test.ScanDirectory DIR [output file]

由上面可以看出,如果我们安装了多个jdk或jre版本的话,使用“java
-XXaltjvm=”
可以通过绝对路径指定到其他版本的jvm.dll上去,至于能不能运行还有待测试。

我们下面回到java.c的main函数中看看上面找到的jvm.dll是如何装载挂接执行的。

该操作大致分为三步:
a、装载jvm.dll动态连接库。
b、初始化jvm.dll并挂接到JNIEnv(JNI调用接口)实例。
c、调用JNIEnv实例装载并处理class类。

实现:
a、装载jvm.dll动态连接库是由main函数调用java_md.c中LoadJavaVM函数实现的。
main函数首先构造了一个InvocationFunctions结构的局部变量,InvocationFunctions
结构有两个函数指针:

typedef struct {
    CreateJavaVM_t
CreateJavaVM;
    GetDefaultJavaVMInitArgs_t
GetDefaultJavaVMInitArgs;
} InvocationFunctions;

函数LoadJavaVM中先调用windows
API函数:LoadLibrary装载jvm.dll动态连接库,
之后将jvm.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs
挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数
指针变量上。jvm.dll的装载工作宣告完成。

b、初始化jvm.dll并挂接到JNIEnv(JNI调用接口)实例是通过java.c中函数:
InitializeJVM完成的。
main方法中首先定义了一个JNIEnv结构的指针,JNIEnv结构中定义了许多与装载class
类文件、查找类方法、调用类方法有关的函数指针变量。InitializeJVM会调用上面
以挂接jvm.dll中JNI_CreateJavaVM的InvocationFunctions结构变量的CreateJavaVM方法,即调用jvm.dll中函数JNI_CreateJavaVM,该函数会将JNIEnv结构的实例返回到main中的JNIEnv结构的指针上。这样main中的JNIEnv指针获取了JNIEnv实例后,就可以开始对class文件进行处理了。

c、调用JNIEnv实例装载并处理class类。
a)如果是执行jar包。
如果执行的是一个jar包的话,main函数会调用java.c中的函数:GetMainClassName,该函数使用JNIEnv实例构造并调用java类:java.util.jar.JarFile中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值,即jar包中文件:
META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。
之后main函数会调用java.c中LoadClass方法装载该主类(使用JNIEnv实例的FindClass)。
b)如果是执行class方法。
main函数直接调用java.c中LoadClass方法装载该类。

然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中
“public
static void main(String[]
args)”方法,并判断该方法是否为public方法,然后调用JNIEnv实例的CallStaticVoidMethod方法调用该java类的main方法。

总结
由上面的代码分析可以看出几个问题。
a、为什么JDK和JRE不一定通过安装,直接拷到硬盘上,设置path环境变量就可以执行。因为java运行获取jre路径的首选方法正是直接通过获取java.exe绝对路径来判断的,如果通过修改注册表选项而不设置path环境变量也可以找到jre路径所在。修改方法如下:
首先我们将java.exe拷到任意目录下,我的拷到e:/temp下,在cmd中运行:
清空path环境变量
E:/temp>set
path=
E:/temp>java
Error opening registry key ‘Software/JavaSoft/Java
Runtime Environment‘
Error: could not find java.dll
Error: could not find
Java 2 Runtime Environment.

导入如下注册表文件(java.reg)

Windows Registry Editor Version
5.00

[HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft]

[HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java
Runtime
Environment]
"CurrentVersion"="1.4"

[HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java
Runtime Environment/1.4]
"JavaHome"="D://java//j2sdk1.4.2_04//jre"

再执行显示执行正常,如下:

E:/temp>java
Usage: java [-options] class
[args...]
           (to
execute a class)
   or  java [-options] -jar jarfile
[args...]
           (to
execute a jar file)

where options
include:
    -client      
to select the "client"
VM
    -server       to
select the "server"
VM
    -hotspot      is a
synonym for the "client"
VM  [deprecated]
                  The
default VM is client.

    -cp <class search path
of directories and zip/jar files>
    -classpath
<class search path of directories and zip/jar
files>
                  A
; separated list of directories, JAR
archives,
                  and
ZIP archives to search for class
files.
    -D<name>=<value>
                  set
a system
property
    -verbose[:class|gc|jni]
                  enable
verbose
output
    -version      print
product version and
exit
    -showversion  print product version
and continue
    -?
-help      print this help
message
    -X            print
help on non-standard
options
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable
assertions
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable
assertions
    -esa |
-enablesystemassertions
                  enable
system assertions
    -dsa |
-disablesystemassertions
                  disable
system assertions

b、java.exe是通过jvm.cfg文件或直接指定jvm.dll路径来装载执行java程序的。
见上面例子。
c、不同实现版本的jvm.dll必然存在一个名为:JNI_CreateJavaVM的导出函数,
java.exe正是通过调用该函数获得JNIEnv调用接口来装载执行class类的。这个
函数也是我们下一步研究java
vm实作技巧的研究出发点。
JNI_CreateJavaVM函数位于:hotspot/src/share/vm/prims/jni.cpp文件中。

时间: 2024-10-28 10:52:49

java源代码分析----jvm.dll装载过程的相关文章

Java通过JNI调用dll详细过程(转)

源:Java通过JNI调用dll详细过程 最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无需再次登录直接进入平台,CS软件方提供了一个加密解密的dll文件,我们需要在action中通过该dll解密,那么就涉及到java调用dll的问题. 首先我选择了JNI方式(因为网上说的另两种方式Jawin, Jacob更不会),大体流程如下: 1.写一个java的class,在类里声明所调用的库名称

C++调用Java方法时jvm.dll相关错误 【每次记录完后都被瞬间解决了……】

在编程的学习过程中,愈发感觉到了女性思维在这方面的局限性. 背景介绍: 为了学习JNI中C++对Java的调用,在阅读<JNI技术手册>的同时加以练习.但根据示例代码编写过程中总出现各种 奇怪的问题(一度后悔自己装了win7 64位系统,而电脑之前是预装win8 32位的...).由于Java部分的代码非常简单, 没有出现任何错误,javac.javah命令也能正常输出.class文件和头文件.但C++部分却报错了.所学习的示例代码意图 通过C++调用Java,生成一个.exe的启动文件. J

启动Eclipse时,出现 “Failed to load the JNI shared library &quot;C:\Program Files\java\jdk1.7.....\jvm.dll&quot;

原因1:给定目录下jvm.dll不存在. 解决方法:(1)重新安装jre或者jdk并配置好环境变量.(2)copy一个jvm.dll放在该目录下. 原因2:eclipse的版本与jre或者jdk版本不一致 解决方法:要么两者都安装64位的,要么都安装32位的,不能一个是32位一个是64位. 先确定Eclipse是多少位的,32 or 64, 在 Eclipse的安装目录下的 eclipse.ini 文件中,"--launcher.library"下,如果有win32.x86,就是32位

Java源代码分析之Vector数组

Vector源码分析 每个Java程序员应该的特性 可变长数组(grow or shrink) 能够使用索引获取值(accessed using an integer index) 多线程环境下线程安全 类图 package java.util; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator; /* vector 通过

【Java高级】JVM内存区域模型和加载过程

JVM内存区域模型 1.方法区 也称"永久代" ."非堆",  它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小. 运行时常量池:是方法区的一部分,Class文件中除了有类的版本.字段.方法.接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中.

Java前端编译:Java源代码编译成Class文件的过程

Java前端编译:Java源代码编译成Class文件的过程 在上篇文章<Java三种编译方式:前端编译 JIT编译 AOT编译>中了解到了它们各有什么优点和缺点,以及前端编译+JIT编译方式的运作过程. 下面我们详细了解Java前端编译:Java源代码编译成Class文件的过程:我们从官方JDK提供的前端编译器javac入手,用javac编译一些测试程序,调试跟踪javac源码,看看javac整个编译过程是如何实现的. 1.javac编译器 1-1.javac源码与调试 javac编译器是官方

JAVA随笔篇一(Timer源代码分析和scheduleAtFixedRate的使用)

写完了基础篇,想了非常久要不要去写进阶篇.去写JSP等等的用法.最后决定先不去写.由于自己并非JAVA方面的大牛.眼下也在边做边学,所以决定先将自己不懂的拿出来学并记下来. Timer是Java自带的java.util.Timer类,通过调度一个java.util.TimerTask任务.这样的方式能够让程序依照某一个频度运行. 1.Timer类的源代码分析: public class Timer { /** * The timer task queue. This data structure

struts2请求过程源代码分析

struts2请求过程源代码分析 Struts2是Struts社区和WebWork社区的共同成果.我们甚至能够说,Struts2是WebWork的升级版.他採用的正是WebWork的核心,所以.Struts2并非一个不成熟的产品,相反.构建在WebWork基础之上的Struts2是一个执行稳定.性能优异.设计成熟的WEB框架. 我这里的struts2源代码是从官网下载的一个最新的struts-2.3.15.1-src.zip.将其解压就可以. 里面的文件夹页文件很的多,我们仅仅须要定位到stru

Android系统进程Zygote启动过程的源代码分析

原文地址:http://blog.csdn.net/luoshengyang/article/details/6747696 Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制:这两个特点都是在进程的初始化过程中实现的,本文将详细分析Android应用程序进程创建过程中是如何实现这两个特点的. Android应用程序框架层创建的应用程序进程的入口函数是ActivityThread.ma