- 浏览: 202089 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
fireway200:
good job good job
深入理解JVM--JVM垃圾回收机制 -
sinat_19635357:
good job
深入理解JVM--JVM垃圾回收机制 -
jayung:
不错,非常感谢
Eclipse正则表达式 替换查找 /* */ 注释 -
yuanwofei:
[c[color=darkblue][color=cyan][ ...
深入理解JVM—JVM内存模型 -
w10001:
非常感谢,花费2个小时,按照楼主的方法终于成功了
ext4.1 spket 1.6.23 Myeclipse10.5 开发环境 extjs代码提示
类的加载的最终产品是位于堆(heap)中的class对象
Class对象封装了类在方法区内的数据结构并向Java程序员提供访问方法区内的数据结构的接口。而反射就像一面镜子一样可这个接口是反射的接口,所以我们可以通过反射获得这个类的方法和属性,包括私有的方法和属性!
下面我们来详细的介绍一下类加载器
类的加载器有两种
1、 Java虚拟机自带的加载器
2、 用户自定义类加载器
而Java虚拟机自带的加载器又包括3种类加载器
? 根类加载器(Bootstrap)
? 扩展类加载器(Extension)
? 系统类加载器(Ststem)
系统类加载器又称为应用类加载器
其中扩展类加载器和系统类加载器是使用Java实现的。而根加载器是使用C++实现的,JVM的API也没有暴露根类加载器,程序员无法在Java代码中获取根加载器。
用户自定义类加载器是用户自己写的类加载器,但是必须继承java.lang.ClassLoader这个类,用户可以自定义类的加载方式!
我们先来看下类加载器的相关API
每个
Class对象都包含了一个对定义的Classloader的定义,也就是说通过Class我们可以拿到对应的Classloader,那我们再来看一下Class这个对象如何拿到Classloader。
Class
对象有一个getClassLoader的方法用于返回该类的类加载器,但有些实现可能使用null来标识引导类加载器(根类加载器)。也就是说当我们使用根加载器加载的对象使用此方法获取到的ClassLoader是null,为什么是这样呢?前面我们也已经说了,根类加载器是使用C++编写的,JVM不能够也不允许程序员获取该类,所以返回的是null,下面还有一句,如果此对象表示的是一个基本类型或void,则返回null,其实进一步的含义就是:Java中所有的基本数据类型都是由根加载器加载的!(JDK1.5以后将void纳入为基本数据类型)!
下面我们通过代码来具体来看一下类的先关加载器!(看下面一段代码)
package com.yhj.jvm.classloader.test; /** * @Description:ClassLoader测试与探究 * @Author YHJ create at 2011-6-25 下午04:08:32 * @FileName com.yhj.jvm.classloader.test.ClassLoaderTest.java */ public class ClassLoaderTest { /** * * @Description:main函数,启动入口 * @param args * @author YHJ create at 2011-6-25 下午04:08:57 * @throws ClassNotFoundException */ public static void main(String[] args) throws ClassNotFoundException { System.out.println(Class.forName("java.lang.String").getClassLoader()); } }
刚才我们已经说了,基本数据类型使用根类加载器加载的,因此本类中java.lang.String获取类加载器返回的结果应该是null。运行结果如下
我们修改一下代码看我们自己写的类是哪个类加载器加载的?
package com.yhj.jvm.classloader.test; /** * @Description:ClassLoader测试与探究 * @Author YHJ create at 2011-6-25 下午04:08:32 * @FileName com.yhj.jvm.classloader.test.ClassLoaderTest.java */ public class ClassLoaderTest { /** * @Description:main函数,启动入口 * @param args */ public static void main(String[] args) throws ClassNotFoundException { System.out.println(Class.forName("com.yhj.jvm.classloader.test.ClassLoaderTest").getClassLoader()); } }
运行结果是什么呢?
我们可以看到运行结果是
AppClassLoader执行的,即应用类加载器(系统类加载器)!
好,具体的细节我们接下来再说!我们先来看一下相关的一些基础内容!
类的加载时机:我们前面提到,所有的类或接口都是在Java虚拟机首次“主动使用”的时候才会初始化,类从class文件到内存经过了“加载”、“连接”、“初始化”,类是在首次主动使用的时候进行初始化,那他是什么时候加载的呢?
类的加载并不需要到该类或接口被首次主动使用的时候才加载,JVM规范允许类加载器在预料到某个类将要被使用时就预先加载它,如果在预先加载工程中遇到了.class文件缺失或存在错误,则类加载器必须在程序主动使用该类的时候 报告LinkageError错误,如果这个类一直没有被程序主动使用,则该类加载器不会报告错误!即使不存在这个类也不会报告错误!
这时候不是异常,是错误哦,看清楚了哦!
一般我们都是和Exception打交道,和Error打交道不太多!打不是Error是由JVM;来处理的!我们来看一下LinkageError这个类的API。
我们看到他是继承自
Error的,LinkageError 的子类指示一个类在一定程度上依赖于另一个类;但是,在编译前一个类之后,后一个类发生了不相容的改变。什么意思呢?举个例子:我们有两个类A和B,B继承自A,我们就说B依赖于A,假设我们都通过JDK1.6编译完成了,但是A又通过JDK1.5重新编译了一次,理论上讲程序是可以正常运行的,但是这时候就会出现新编译的A不兼容B中指定的A,就会抱着个一个错误!
我们在做web开发的过程中,假设我们的程序是在JDK1.6上编译完成,拿到服务器JDK1.5的环境下运行就可能报出这么一个错误!但是反过来,我们拿1.5编译通过的程序放在1.6上运行,是可以的。因为程序都是向前兼容的,但是从1.6拿到1.5,有可能是好的,也有可能就报出这么一个错误!
类加载完毕之后进入到连接阶段,连接就是将已读入到内存的类的二进制数据合并到虚拟机的运行时环境中去!在连接之前,所有的class文件都是单个的文件,之间没有任何联系,只有JVM把他们连接起来,才能将他们之间的关系有机的结合起来!
类的验证包括一下四个方面
–类文件的结构检查
–语义检查
–字节码验证
–二进制兼容性的验证
JDK为了保证class文件的安全性,在加载完成之后又进行了一系列的验证,这些个验证很多在编译的时候已经做过了,但是我们前面已经提到了,很多class字节码文件不是通过javac实现的,例如eclipse就是通过JTA实现的,而我们也可以自己随便写一个.class的文件让他加载,因此为了安全期间,JVM又进行了一次校验!
具体参加《深入Java虚拟机第二版》,如下
类的准备阶段
类的解析阶段
这里我们解释一下符号引用和直接引用,在Java语言里面我们说是没有指针的,但是我们看到上图中,car调用了car类定义的run方法,而worker类中是没有car的run的,因此在运行的时候JVM把这个有一个符号和银行替换为一个指针(这里指替换为真正的由C++底层实现的指针),而我们java里面看到的就是符号引用,实际C++执行的才是指针,我们称之为直接引用!
类的初始化
这个时候我们再来看上次那段比较诡异的代码
package com.yhj.jvm.classloader; /** * @Description:单例初始化探究 * @Author YHJ create at 2011-6-4 下午08:31:19 * @FileName com.yhj.jvm.classloader.ClassLoaderTest.java */ class Singleton{ private static Singleton singleton=new Singleton(); private static int counter1; private static int counter2 = 0; public Singleton() { counter1++; counter2++; } public static int getCounter1() { return counter1; } public static int getCounter2() { return counter2; } /** * @Description:实例化 * @return * @author YHJ create at 2011-6-4 下午08:34:43 */ public static Singleton getInstance(){ return singleton; } } /** * @Description: 测试启动类 * @Author YHJ create at 2011-6-4 下午08:35:13 * @FileName com.yhj.jvm.classloader.ClassLoaderTest.java */ public class ClassLoaderTest { /** * @Description:启动类 * @param args * @author YHJ create at 2011-6-4 下午08:30:12 */ @SuppressWarnings("static-access") public static void main(String[] args) { Singleton singleton=Singleton.getInstance(); System.out.println("counter1:"+singleton.getCounter1()); System.out.println("counter2:"+singleton.getCounter2()); System.out.println(singleton.getClass().getClassLoader()); } }
我们调用Singleton singleton=Singleton.getInstance();调用Singleton的静态方法,相当于主动使用了类Singleton,因此Singleton被初始化!
当我们看到显示的是
private static Singleton singleton=new Singleton(); private static int counter1; private static int counter2 = 0;
这样的时候,顺序执行,先赋予初始值,singleton为null,counter1为0,counter2为0,然后顺序对singleton赋予正确的值new Singleton(),执行构造函数,counter1增加变为1,然后counter2变为1,然后继续执行初始化,将counter2赋值为正确的值,将counter2修改为0,因此运行结果是1、0
反过来
private static int counter1; private static int counter2 = 0; private static Singleton singleton=new Singleton();
先赋予初始值counter1为0,counter为0,singleton为null,然后对counter2赋值为正确的值,counter2为0,然后对singleton执行初始化赋予正确的值new Singleton(),执行构造函数,counter1为1,counter2为1,因此执行结果是1、1
到此,是不是感觉前面的问题豁然开朗了呢?
发表评论
-
深入理解ClassLoader(五)—类的卸载
2012-06-28 10:37 1909我们知道,当一个类被加载、连接和初始化之后,他的生命周期 ... -
深入理解ClassLoader(四)—类的父委托加载机制
2012-06-28 10:35 2445上几次我们介绍到了JVM内部的几个类加载器,我们来重新画 ... -
深入剖析ClassLoader(三)—编译常量、类加载器深入剖析
2012-06-28 10:33 1228类的初始化 静态变量的生民语句以及静态代码块都被看作类 ... -
深入剖析Classloader(一)--类的主动使用与被动使用
2012-06-28 10:28 1301我们知道 java 运行的是这样的,首先 ... -
ext4.1 spket 1.6.23 Myeclipse10.5 开发环境 extjs代码提示
2012-06-27 10:26 5238用于在spket中进行提醒时的筛选。以下是具体的操作步骤 ... -
Eclipse HTMLEditor 下载安装
2012-06-26 17:13 1292需求:需要在eclipse里面编辑html和jsp,语法 ... -
MyEclipse 10.5 下载 破解
2012-06-26 08:22 249官方下载地址(Windows) ... -
MyEclipse 10.5 下载
2011-11-04 11:36 159Myeclipse 10.5(Windows) ... -
CAS sso单点登录 架设中问题及解决方案
2011-05-20 09:02 5790<转> 1.在CAS ... -
CAS 单点登录完整教程 【转】
2011-05-20 08:53 6701一、教程前言 教程 ... -
Myeclipse 9.0 10.0安装 SVN 插件
2011-03-28 16:21 5796方法一: 安装subclipse, SVN 插件 1、从官 ... -
MyEclipse 9.0 正式版 破解 注册机 新鲜出炉
2011-03-08 22:08 9935[原文] http://www.byshang.org/doc ... -
commons-beanutils 复制 bean 属性
2011-02-28 09:42 1598commons-beanutils是jakarta com ... -
MyEclipse 9.0 M2 官方下载地址
2011-02-10 11:43 6754注册机 现在已经出来了 大家赶紧下载去吧 下载地址:ht ... -
Eclipse正则表达式 替换查找 /* */ 注释
2010-12-13 15:53 8447最近几天用jd-gui反编译了一个springMVC的项 ... -
Myeclipse9.0安装VSS插件
2010-12-13 10:07 4006一、下载VSS插件 可以去官方网站下载,也可以在这里http: ...
相关推荐
classloader教程 --- from IBM
ClassLoader类加载器讲解,理解JAVA类加载机制
ClassLoader的API使用和自定义
类加载器分为根加载器(bootstrap classloader)、扩展类加载器(ext classloader)、系统类加载器(system classloader)、自定义类加载器(通常继承java.net.URLClassLoader,重写findClass()),它们的关系通常...
【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!
类加载器是 Java 语言的一个创新,也是 ...不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试 ClassNotFoundException和 NoClassDefFoundError等异常。
关于类加载器的 上课ppt -java虚拟机自带的加载器 根类加载器(Bootstrap) c++写的看不到扩展类加载器(extension) 系统类加载器(System) AppClassLoad 用户自定义的类加载器 Java.lang.ClassLoader的子类
Java的类加载机制:加载,连接,初始化。JAVA类加载器: Bootstrap ClassLoader : 根类加载器, Extension ClassLoader: 扩展类加载器, System ClassLoader : 系统类加载器, Java反射
3-7Tomcat中自定义类加载器的使用与源码实现(1).mp4
java classloader 讲义-淘宝网
java应用程序类加载器(ClassLoader for java Application),类似exe4j, 方便启动java程序, 配置灵活,支持多平台选择性配置
如果户创建的JAR放在此录下,也会动由扩展类加载器加载.应程序类加载器(系统类加载器,Application ClassLoader)java语编写,由sun.
类加载器是 Java 语言的一个创新,也是 ...不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试 ClassNotFoundException和 NoClassDefFoundError等异常。
java源码源码类加载器泄漏预防库 如果您想避免可怕的java.lang.OutOfMemoryError: Metaspace / PermGen space ,只需将此库包含到您的 Java EE 应用程序中,它就会处理剩下的事情! 要了解有关类加载器泄漏、其原因...
LazyWorker.zip,一个智能控制进入电子邮件地址,自动检查是否存在域,如果域可以接收电子邮件。LaZyWork是一个帮助类延迟任务。例如,检查需要网络操作且不应在每次按键关闭后进行的输入。
【IT十八掌徐培成】Java基础第25天-04.classLoader-系统资源-不可见类访问.zip
ClassLoader类加载机制和原理详解
下面小编就为大家带来一篇classloader类加载器_基于java类的加载方式详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
jvm运行的过程中,需要载入类,而类的加载需要类加载器,本文章提供了java的类加载器的工作原理。可以使读者更加理解jvm的运行机制。
类加载器是Java最强大的特征之一。但是开发者常常忘记类加载组件。类加载器是在运行时负责寻找和加载类文件的类。Java允许使用不同的类加载器,甚至自定义的类加载器。类加载器从源文件(通常是.class 或 .jar文件)...