- 浏览: 663433 次
- 性别:
- 来自: 宇宙中的某个角落
文章分类
- 全部博客 (244)
- Java SE (57)
- EJB3.0 (7)
- Architecture (15)
- DDD (4)
- UML&GOF Patterns (17)
- scala (0)
- hadoop (1)
- Hibernate&JPA (8)
- webwork (2)
- Problems and Solution (3)
- search engine (Lucene) (4)
- .net C# (2)
- Web develop (9)
- OS(windows&linux) (2)
- Software Engineering (0)
- Resource shara (5)
- Javascript (1)
- apple (1)
- Data structure (11)
- English study (32)
- Assembly language (2)
- Feeling&emotion (5)
- Diary (23)
- Entertainment (17)
- 诗词赏析 (8)
- 道德经 (1)
- ios (5)
最新评论
-
zhuzf:
写的太好了
实例分析Java Class的文件结构 -
随便小屋:
写的太好了,Mark一下,楼主辛苦了!
实例分析Java Class的文件结构 -
lowkey2046:
引用 应用程序注册读就需事件和相关联的事件处理器应该是读就绪吧 ...
高性能IO设计的Reactor和Proactor模式 -
BigBird2012:
“JVM引入了分代收集的策略,其中对新生代采用"Ma ...
JVM内存模型以及垃圾收集策略解析 -
xuelian2010:
找到合适的人做正确的事情!!!
三月份辞职创业,北京第一家线下体验店成功开张,伙伴们加油!
JAVA中类文件加载是动态的。JVM指令是被封装在了. class文件里面,而.class文件的加载过程是动态的,也就是说当我们用到的时候才会去加载,如果不用的话,就不会去加载我们的类。这里所说的用到包括两种方式,第一种就是new一个对象的时候(这个时候要特别注意,当设计到多态的时候,就会有一点点变化,这时候编译器会做一些优化,这样以来当加载的时候会提前加载设计到多态的类,关于这一点下面有个例子(example 1)来说明。另一种就是当一个类的静态代码被调用的时候。
运行此测试程序结果如Example1.1图 :
Example 1.1
当我们注释掉Example.1.1行时,运行Example1.2行,结果如下:
Example 1.2
分析以上两图的运行结果我们可以看出:当我们将子类对象赋值给父类时,编译器会做一点优化,于是加载器在还没有new 子类对象的时候已经加载了父类以及子类(example1.1结果),当不存在多态的时候,我们可以看到是当要new Dog()的时候才会加载Dog以及父类。无论何种方式,在new之前,类确实已经加载到了内存中。
JAVA为我们提供了两种动态机制。第一种是隐式机制。其实new一个对象和调用类的静态方法时,就是隐式机制在工作。第二种是显示机制。显示的机制又有两种策略(第一种是用java.lang.Class的forName(String str)方法,第二种是用java.lang.ClassLoader的loadClass())。
第一种:利用forName方法
当我们查API文档就会发现forName方法有两种形式。分别如下:
public static Class<?> forName(String className)
throws ClassNotFoundException
public static Class<?> forName(String name,
boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
先来说说第二种方法:第二个方法值得注意的就是第二个参数boolean initialize,如果我们把这个参数设置为false,那么当我们加载完类后就不会执行静态代码和静态的初始化动作。只有当我们new一个对象的时候才会初始化。而第三个参数是用来指明类的加载器的。
如果查看java.lang.Class类的源代码,上述两种方法最终都会调用Class类中的私有的native方法forName0(),此方法的声明如下:
private static native Class forName0(String name, boolean init , ClassLoader loader)
throws ClassNotFoundException;
所以当我们调用Class.forName(name )时,其实是在方法内部调用了:
forName0(name, true, ClassLoader.getCallerClassLoader());
当我们调用Class.forName(name, initialize, loader )的时候,实际上此方法内部调用了:
forName0(name, initialize, loader);
下面看一个例子,如果方法中第二个参数为false的情况:
Example 2.1
从上图可以看出来类加载完成后并没有立即执行静态初始化代码,而是到了实例化的时候才进行了静态初始化。有时候我们会说静态代码是在类第一次被加载时执行的,并且只执行一次。其实这是对与new一个对象,第一次访问类的静态代码以及第二个参数为true时而言的,对于动态的加载来说,如果forName方法的第二个参数设置为false,那么就是在实例化的时候才会执行静态初始化。当然默认情况下第二个参数是true.
第二种方法:利用Class对象获取的ClassLoader装载。
下面是一个简单的例子:
Example 2.2
从上图可以看出loader完成以后并没有立即进行静态代码的执行。只有当newInstance()的时候才执行静态初始化,这和把
public static Class forName(String name, boolean initialize, ClassLoader loader)的第二个参数指定为false的情况完全一样。其实每当我们写完一个编译单元以后就会得到一个.calss文件,这个文件中就包含了该类的Class对象。JVM就是利用这个class对象来进行动态装载类的。
呵呵终于总结玩了。如果有什么地方理解有误的,请各位前辈和各位兄弟指点。谢谢。。
//example 1 // Zoo.java abstract class Animal { Animal(){ System.out.println("Animal constructor"); } } class Tiger extends Animal { Tiger(){ System.out.println("Tig constructor "); } } class Dog extends Animal { Dog(){ System.out.println("Dog Constructor "); } } public class Zoo { private Animal am; //Example 1.1 //private Dog am; Example 1.2 private Tiger tiger; Zoo(){ am = new Dog(); tiger = new Tiger(); } public static void main(String [] args){ System.out.println("new Zoo before"); Zoo z = new Zoo(); System.out.println("new Zoo after "); } }
运行此测试程序结果如Example1.1图 :
Example 1.1
当我们注释掉Example.1.1行时,运行Example1.2行,结果如下:
Example 1.2
分析以上两图的运行结果我们可以看出:当我们将子类对象赋值给父类时,编译器会做一点优化,于是加载器在还没有new 子类对象的时候已经加载了父类以及子类(example1.1结果),当不存在多态的时候,我们可以看到是当要new Dog()的时候才会加载Dog以及父类。无论何种方式,在new之前,类确实已经加载到了内存中。
JAVA为我们提供了两种动态机制。第一种是隐式机制。其实new一个对象和调用类的静态方法时,就是隐式机制在工作。第二种是显示机制。显示的机制又有两种策略(第一种是用java.lang.Class的forName(String str)方法,第二种是用java.lang.ClassLoader的loadClass())。
第一种:利用forName方法
当我们查API文档就会发现forName方法有两种形式。分别如下:
public static Class<?> forName(String className)
throws ClassNotFoundException
public static Class<?> forName(String name,
boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
先来说说第二种方法:第二个方法值得注意的就是第二个参数boolean initialize,如果我们把这个参数设置为false,那么当我们加载完类后就不会执行静态代码和静态的初始化动作。只有当我们new一个对象的时候才会初始化。而第三个参数是用来指明类的加载器的。
如果查看java.lang.Class类的源代码,上述两种方法最终都会调用Class类中的私有的native方法forName0(),此方法的声明如下:
private static native Class forName0(String name, boolean init , ClassLoader loader)
throws ClassNotFoundException;
所以当我们调用Class.forName(name )时,其实是在方法内部调用了:
forName0(name, true, ClassLoader.getCallerClassLoader());
当我们调用Class.forName(name, initialize, loader )的时候,实际上此方法内部调用了:
forName0(name, initialize, loader);
下面看一个例子,如果方法中第二个参数为false的情况:
//example 2.1 // Zoo.java abstract class Animal { static { System.out.println("Animal static code block "); } Animal(){ System.out.println("Animal constructor"); } } class Tiger extends Animal { Tiger(){ System.out.println("Tig constructor "); } } class Dog extends Animal { Dog(){ System.out.println("Dog Constructor "); } } public class Zoo { public static void main(String [] args)throws Exception { System.out.println("new Zoo before"); Zoo z = new Zoo(); Class c = Class.forName("Dog",false,z.getClass().getClassLoader()); System.out.println("initilize before "); Animal dog = (Animal)c.newInstance(); System.out.println("new Zoo after "); } }
Example 2.1
从上图可以看出来类加载完成后并没有立即执行静态初始化代码,而是到了实例化的时候才进行了静态初始化。有时候我们会说静态代码是在类第一次被加载时执行的,并且只执行一次。其实这是对与new一个对象,第一次访问类的静态代码以及第二个参数为true时而言的,对于动态的加载来说,如果forName方法的第二个参数设置为false,那么就是在实例化的时候才会执行静态初始化。当然默认情况下第二个参数是true.
第二种方法:利用Class对象获取的ClassLoader装载。
下面是一个简单的例子:
//Example 2.2 //Zoo.java abstract class Animal { static { System.out.println("Animal static code block "); } Animal(){ System.out.println("Animal constructor"); } } class Tiger extends Animal { Tiger(){ System.out.println("Tig constructor "); } } class Dog extends Animal { Dog(){ System.out.println("Dog Constructor "); } } public class Zoo { public static void main(String [] args)throws Exception { Class c = Zoo.class; ClassLoader loader = c.getClassLoader(); System.out.println("loader before"); Class dog = loader.loadClass("Dog"); System.out.println("instance before "); Animal an = (Animal)dog.newInstance(); } }
Example 2.2
从上图可以看出loader完成以后并没有立即进行静态代码的执行。只有当newInstance()的时候才执行静态初始化,这和把
public static Class forName(String name, boolean initialize, ClassLoader loader)的第二个参数指定为false的情况完全一样。其实每当我们写完一个编译单元以后就会得到一个.calss文件,这个文件中就包含了该类的Class对象。JVM就是利用这个class对象来进行动态装载类的。
呵呵终于总结玩了。如果有什么地方理解有误的,请各位前辈和各位兄弟指点。谢谢。。
发表评论
-
Java高级软件攻城狮,你在哪里?
2013-09-17 11:19 0PS:管理员同志, ... -
Java高级软件攻城狮,你在哪里?
2013-09-17 09:46 5创业一年,感触颇多,也走过一些弯路,不过总体上还好。 ... -
Java高级软件攻城狮,你在哪里?我们需要你....
2013-09-06 13:43 88创业一年,感触颇 ... -
实例分析Java Class的文件结构
2013-01-30 11:11 5127今天把之前 ... -
Java自定义URL协议
2011-08-31 18:26 7021Java 提供了对 URL 协议进行扩展 ... -
JDK 1.6.0_13 Jaxb的一个Bug
2011-05-10 16:50 2334项目中使用jaxb进行xml binding,但是在jdk1. ... -
Apache+PHP+Mysql的搭建
2010-08-05 19:29 1621以前都是用JAVA,PHP没用过,今天因为一些原因,需 ... -
JVM内存模型以及垃圾收集策略解析【续】
2010-02-22 20:00 7368今天接着补全上篇博文 ... -
JVM内存模型以及垃圾收集策略解析
2010-02-21 21:19 10030首先祝大家春节愉快,几个月前研究了一下JVM的内存模型,整理学 ... -
Java类加载器解析
2008-08-10 19:03 2247作者:狂放不羁 网址:http://yuquan-nana.i ... -
捕获checked exception后什么都不做的代价
2008-05-09 13:03 1734最近在做一个小项目,做到注册模块的时候,如果查询数据库后,发现 ... -
Three kinds of attributes in servlet
2008-03-02 00:21 1490There are three kinds of attrib ... -
My first Android programe!
2007-11-18 12:26 1387Today,i writed my first Android ... -
Java是剑客;.NET是刀客(转载)
2007-10-21 22:22 1470剑,一把好剑,重 ... -
高级语言发展简图
2007-09-30 15:35 1869C/C++语言谱系图 -
C#,C++ 与JAVA
2007-09-30 15:31 1718C#(C-Sharp)是Microsoft的新编程语言,被誉为 ... -
[转帖]利用Eclipse编辑中文资源文件
2007-09-09 03:57 4826如果经常使用Struts,并做过国际化操作的人来说,对于中文资 ... -
JAVA类加载器
2007-09-01 20:12 1731Java中加载器的种类大致可以分为四种:Bo ... -
小游戏
2007-08-28 16:48 1830偶前段时间写的小游戏。呵呵。。 -
今天起的早
2007-08-28 06:25 1275呵呵,今天早上很早就醒了。。记录一下这早起的早晨。
相关推荐
Java的类加载机制:加载,连接,初始化。JAVA类加载器: Bootstrap ClassLoader : 根类加载器, Extension ClassLoader: 扩展类加载器, System ClassLoader : 系统类加载器, Java反射
Java语言的类加载机制是其运行时环境的重要组成部分,它负责将类的字节码文件从磁盘、网络或其他数据源加载到JVM(Java虚拟机)中,并转化为可以执行的Java对象。类加载机制包括加载、验证、准备、解析和初始化五个...
动态加载类是Java反射机制的重要应用场景之一。通过`Class.forName()`方法或者`ClassLoader`的`loadClass()`方法,可以根据类名字符串在运行时加载类。 #### 七、操作成员 - **创建对象**:使用`Class`对象的`new...
### Java 类加载机制详解 Java 类加载机制是Java运行时环境的一个核心组成部分,它负责将编译后的Java字节码加载到JVM中,并确保Java应用程序能够正确地运行。类加载机制不仅涉及到类的加载、验证、准备、解析和...
通过阅读资料,你可以了解到注解的应用场景、反射的API用法、字节码的结构以及类加载机制的工作流程。而源代码分析将加深你对这些概念的实际运用。 总之,掌握Java注解、反射、字节码和类加载机制对于提升Java开发...
反射机制和类加载机制是Java编程语言中的两个重要概念。反射提供了强大的运行时元数据操作能力,而类加载机制则确保了类的安全加载和动态管理。深入理解这两个机制对于Java开发者来说至关重要,尤其对于那些从事框架...
### Java反射机制与动态加载实例类 在Java中,反射是一种强大的工具,允许程序在运行时检查和修改其结构和行为。通过反射,我们可以动态地加载类、创建对象、访问和修改字段、调用方法等。本文将深入探讨Java反射...
Java反射机制是Java语言的一个重要特性,它允许程序在运行时获取类的信息并操作对象。Java反射机制的主要作用包括:获取类的所有属性和方法、构造动态实例、调用类的方法等。通过反射,程序可以动态地创建对象和调用...
在“java 类加载器 加密”这个主题中,我们将探讨如何利用类加载器实现类的加密和解密,以及如何通过反射执行main方法。 首先,我们理解一下类加载器的工作原理。Java中的类加载器主要有三种:Bootstrap ...
Java 反射机制允许 Java 程序在运行时动态地加载和调用类的方法。通过反射机制,可以实现动态地加载和执行 Java 类文件。 除了实现动态类加载机制外,还可以应用于网络教学环境中。通过开发基于 C/S 结构模式的...
### JAVA类加载机制与动态代理 #### 一、类加载机制 ##### 1.1 类加载的时机 类加载机制负责将描述类的数据从`.class`文件加载到内存,并进行必要的校验、转换解析和初始化,使之成为可以被Java虚拟机直接使用的...
在Java中,反射机制主要通过java.lang.Class类和相关的类库来实现,它使得我们能够在运行时动态地获取类的信息(如类名、属性、方法等)并能创建和调用对象。 1. **类的加载与Class对象** 当Java虚拟机(JVM)加载一...
JAVA 类加载机制是Java平台核心特性之一,它关乎到程序的运行时环境和代码的动态加载。理解这一机制有助于开发者解决与对象创建、配置问题、应用程序发布等相关的问题。以下是关于JAVA 类加载机制的详细分析: 首先...
Java中的反射机制为开发者提供了一种强大而灵活的方式来处理类信息。通过反射,可以实现诸如动态代理、框架开发等高级功能,同时也可以用于构建高度可扩展和可维护的软件系统。然而,需要注意的是,反射操作可能会...
Java 程序在运行期间可以动态加载、解析和使用一些在编译阶段并不确定的类型数据,这一机制被称为反射(Reflection)。反射库(reflection library)提供了一个非常丰富且精心设计的工具类,以便编写能够动态操纵Java...
总的来说,"JAVA反射机制的入门代码"是初学者理解Java反射机制的好教材,通过它,你可以学习如何动态地操作Java类,提高代码的灵活性,并掌握处理`properties`文件的基础方法。在深入学习和实践中,你将进一步理解...
Java反射机制使得程序在运行时能够动态加载、解析和使用未知类型的类。这为开发者提供了强大的灵活性,比如在设计和运行时添加新类,或者动态查询和操作类的能力。通过反射,我们可以: 1. 加载运行时才能确定的...
9. **分析Java反射Class类型的源代码**:深入理解反射机制的工作原理,了解Class文件的结构以及JVM如何加载类对象以支持反射操作。 #### 四、Java反射原理分析 1. **Class文件结构**:每个编译后的Java类都会生成...