深入理解jre,classload,类加载过程
来源:互联网 发布:爱普生手机打印软件 编辑:程序博客网 时间:2024/06/06 00:04
1.JRE目录:
java runtime environment顾名思义,就是java运行环境。
解释参见http://blog.csdn.net/liufeng_cp/article/details/2674317
这就是JRE的目录核心就是两个:
JVM:java虚拟机 (我个人的理解就是bin目录)
lib:基本类库,提供java编程最基本的API (lib目录)
http://docs.oracle.com/javase/6/docs/technotes/tools/windows/jdkfiles.html
简单一下:
JDK目录
c:\jdk1.6.0 根目录
c:\jdk1.6.0\bin:jdk中可执行文件的目录
开发工具中会用到的一些文件 (区别jre里面的lib)
c:\jdk1.6.0\lib:
如: tools.jar它是包含一些支持jdk使用的非核心类,解压可以看到里面的内容
同时还包含
dt.jar
, 决定交互开发工具(IDE)如何展示java组件
JRE的目录
c:\jdk1.6.0\jre
java运行环境的根目录,JDK开发工具会用到它。这个目录通常是系统环境变量 java.home指向的目录
c:\jdk1.6.0\jre\bin Java平台使用的工具和类库的可执行文件和DLLs文件。这些可执行文件和/jdk1.6.0/bin中的一样。
c:\jdk1.6.0\jre\bin\client 包含Java HotSpotTM 虚拟机客户端所使用到的DLL文件
c:\jdk1.6.0\jre\bin\server 包含Java HotSpotTM 虚拟机服务端所使用到的DLL文件
c:\jdk1.6.0\jre\lib 核心类库,配置,资源文件等 (下面第5部分会提到这个的内容)
如:
rt.jar
:引导类 (包含java平台核心API的运行时类) rt-->runtime
charsets.jar:字符转换类
ext目录 :java平台扩展包存放的目录
还有很多这里先略
http://bbs.csdn.net/topics/340164501
http://www.cnblogs.com/echomyecho/p/3334617.html
2.运行起来
有了这个就可以运行java的程序了--------.class文件
上面bin目录中有一个java.exe ,我们调用它去运行class文件,即是开启一个JVM进程。我们的程序开启的线程等等都是在这个进程中的
(注意:运行一次就是一个进程(注意不是线程),进程的特点就是:独立的资源 私有地址空间 A不能访问B地址空间)(线程则 拥有自己的堆栈,程序计数器,局部变量。但不拥有系统资源,多个线程共享父进程里的全部资源)
如果我们有一个Hello.java文件
(注:为什么我们可以直接用System这个类?因为编译器会自动帮我们import上java.lang的)参见http://blog.sina.com.cn/s/blog_56f69c6601016erf.html
先编译Hello.java得到hello.class文件,我们就可以java hello 来运行这个程序了
执行java hello会发生什么:
(http://my.oschina.net/xianggao/blog/70826)
1)寻找jre目录,寻找jvm.dll,并初始化JVM;
2)产生一个Bootstrap Loader(引导类加载器);
3)Bootstrap Loader自动加载Extended Loader(扩展类加载器),并将其父Loader设为Bootstrap Loader。
4)Bootstrap Loader自动加载AppClass Loader(系统类加载器),并将其父Loader设为Extended Loader。
5)最后由AppClass Loader加载HelloWorld类。
3.类的生命周期
加载-------------------->连接----------------------->初始化------->使用-------> 卸载
(验证------->准备------->解析 )
(连接包含了验证准备解析三个过程)
虚拟机规范严格规定 有且只有 5中情况必须立即对类 初始化(加载、连接自然必须已经发生)
1)遇到new getstatic putstatic invokestatic
2)使用java.lang.reflect包的方法使用反射对类进行调用时
3)初始化一个类,如果发现其父类还未初始化,先触发父类的初始化
4)虚拟机启动时,用户需要指定执行的主类(包含main),会初始化这个主类
5)使用JDK1.7的动态语言支持
执行java hello就属于上面的第4种情况
4.加载器
系统提供三种加载器:
1.bootstrap classloader引导加载器 由JVM提供
(HotSpot虚拟机的引导加载器是c++编写的,JRockit和J9都有引导加载器的java类,但关键代码任然是JNI回调到C的实现)【bootstrap classloader的实例用户是获取不到的】
2.extension classloader扩展加载器 (独立于JVM之外)
3.Application classloader 系统加载器 (独立于JVM之外) (也有书里面说叫system classloader)
我们也可以自定义加载器
加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例(实例的 newInstance()方法就可以创建出该类的一个对象)
(参见http://www.ibm.com/developerworks/cn/java/j-lo-classloader/)
补充:
关于JVM是如何判定两个 Java 类是相同的: A.类的全名 B.加载此类的类加载器
5.加载过程
1)启动类加载器(Bootstrap ClassLoader):负责加载JAVA_HOME\lib目录(见上面第1部分内容)中并且能被虚拟机识别的类库到JVM内存中,如果名称不符合的类库即使放在lib目录中也不会被加载。该类加载器无法被Java程序直接引用。
URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();for(URL url:urls){System.out.println(url.toExternalForm());}
结果:file:/C:/java/jdk1.7/jre/lib/resources.jar
file:/C:/java/jdk1.7/jre/lib/rt.jar
file:/C:/java/jdk1.7/jre/lib/sunrsasign.jar
file:/C:/java/jdk1.7/jre/lib/jsse.jar
file:/C:/java/jdk1.7/jre/lib/jce.jar
file:/C:/java/jdk1.7/jre/lib/charsets.jar
file:/C:/java/jdk1.7/jre/lib/jfr.jar
file:/C:/java/jdk1.7/jre/classes
这就是引导类加载器负责加载的类(仅按文件名识别 如rt.jar 文件名不符合的即使放在lib目录下也不会被加载)
2)扩展类加载器(Extension ClassLoader):主要是负责加载JAVA_HOME\lib\ext目录中的类库,该加载器可以被开发者直接使用。
3)应用程序类加载器(Application ClassLoader):该类加载器也称为系统类加载器,它负责加载用户类路径(Classpath)上所指定的类库,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
双亲委派模型
工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。
Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如java.lang.Object类,无论哪个类加载器去加载该类,最终都是由启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。否则的话,如果不使用该模型的话,系统中将出现多个java.lang.Object,导致混乱。
(注:即使自定义类加载器,强行使用defineClass()去加载java.lang开头的类 还是会报:java.lang.SecurityException)
ClassLoader类中loadClass()方法关键代码如下:
// First, check if the class has already been loadedClass c = findLoadedClass(name);if (c == null) {try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.c = findClass(name);}
先检查是否已经被加载过,如果没有则调用父加载器的loadClass()方法,如果父加载器为空则默认使用启动类加载器作为父加载器。如果父类加载器加载失败,则先抛出ClassNotFoundException,然后再调用自己的findClass()方法进行加载。
6.加载器各个方法
findClass的部分代码
<span style="font-size:18px;"> byte[] classfile;InputStream in = this.getClass().getResourceAsStream(jarname);classfile = ClassPoolTail.readStream(in);return defineClass(name, classfile, 0, classfile.length);</span>
return的类型是Class<?>
- 深入理解jre,classload,类加载过程
- java 类加载ClassLoad
- 深入理解JVM类加载过程
- 深入理解JVM07--虚拟机类加载机制--类加载过程
- 深入理解java虚拟机(八)类加载过程详解
- 深入理解Java虚拟机笔记---类加载过程
- 《深入理解Java虚拟机》:类加载的过程
- [深入理解Java虚拟机]第七章 类加载的过程
- 深入理解JVM之四:类加载过程
- 深入理解JVM(九)——类加载的过程
- 深入理解JVM(九)——类加载的过程
- 深入理解JVM(九)——类加载的过程
- 深入理解JVM(九)——类加载的过程
- Tomcat ClassLoad加载机制
- 深入理解JVM-虚拟机加载机制-类加载过程
- 深入理解 Tomcat(五)源码剖析Tomcat 启动过程----类加载过程
- 深入理解Java类加载
- 深入理解Java类加载
- DLL-LoadLibrary函数
- eclipse下去掉js编译
- QQ空间营销七大注意事项
- Java HashMap的工作原理
- spring初始化和销毁bean
- 深入理解jre,classload,类加载过程
- poj 2386 bfs
- 【连通图|强连通分量+最长路】POJ-3592 Instantaneous Transference
- Java动态 遍历List 时删除List特征元素 异常问题 及解决方式总结
- 面试1
- hdu2276---Kiki & Little Kiki 2(矩阵)
- Android笔记--ThreadLocal,Looper,Handler,Message,MessageQueue的关系
- Java线程:概念与原理
- 逗比验证码第二期 php代码