- 浏览: 200479 次
- 性别:
- 来自: 紫禁城
文章分类
最新评论
-
a1439226817:
<!doctype html><html l ...
发布一个支持N级下拉列表联动的控件 -
a1439226817:
也不高个测试的demo,别人怎么用啊
发布一个支持N级下拉列表联动的控件 -
davaidgao:
不全啊,这是
Spring3.x权威开发指南 -
caizi12:
对于map绑定很是不方便,现在的做法,需要创建一User类,再 ...
浅谈 SpringMVC 数据绑定 -
joeyhuang:
不全啊..
Spring3.x权威开发指南
一 . 面向接口编程. 不要面向类编程.
二 . 关于异常:
如果父类的一个方法抛出了异常,子类在重写此方法时可以不抛出异常而直接处理,也可以抛出父类异常的子异
常,但是不能抛出比父类方法抛出的异常级别更高的异常.
三 . Java的类装载器(Class Loader)和命名空间(NameSpace)
1.摘要:
Java的类装载器是Java动态性的核心,本文将向大家简要介绍Java的类装载器,及相关的双亲委派模型,命名
空间,运行时包等概念,同时讨论一些在学习中容易混淆的问题。
2.类装载器的功能及分类:
顾名思义,类装载器是用来把类(class)装载进JVM的。JVM规范定义了两种类型的类装载器:启动内装载器
(bootstrap)和用户自定义装载器(user-defined class loader)。
bootstrap是JVM自带的类装载器,用来装载核心类库,如java.lang.*等。由例1可以看出,java.lang.Object
是由bootstrap装载的。
Java提供了抽象类ClassLoader,所有用户自定义类装载器都实例化自ClassLoader的子类。
System Class Loader是一个特殊的用户自定义类装载器,由JVM的实现者提供,在编程者不特别指定装载器的
情况下默认装载用户类。系统类装载器可以通过ClassLoader.getSystemClassLoader() 方法得到。
例1,测试你所使用的JVM的ClassLoader
/*LoaderSample1.java*/
public class LoaderSample1
{
public static void main(String[] args)
{
Class c;
ClassLoader cl;
cl = ClassLoader.getSystemClassLoader();
System.out.println(cl);
while (cl != null)
{
cl = cl.getParent();
System.out.println(cl);
}
try
{
c = Class.forName(“java.lang.Object”);
cl = c.getClassLoader();
System.out.println(“java.lang.Object’s loader is ” + cl);
c = Class.forName(“LoaderSample1”);
cl = c.getClassLoader();
System.out.println(“LoaderSample1’s loader is ” + cl);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
在我的机器上(Sun Java 1.4.2)的运行结果
sun.misc.Launcher$AppClassLoader@1a0c10f
sun.misc.Launcher$ExtClassLoader@e2eec8
null
java.lang.Object's loader is null
LoaderSample1's loader is sun.misc.Launcher$AppClassLoader@1a0c10f
第一行表示,系统类装载器实例化自类sun.misc.Launcher$AppClassLoader
第二行表示,系统类装载器的parent实例化自类sun.misc.Launcher$ExtClassLoader
第三行表示,系统类装载器parent的parent为bootstrap
第四行表示,核心类java.lang.Object是由bootstrap装载的
第五行表示,用户类LoaderSample1是由系统类装载器装载的
3.双亲委派模型:
从1.2版本开始,Java引入了双亲委托模型,从而更好的保证Java平台的安全。在此模型下,当一个装载器被请
求装载某个类时,它首先委托自己的parent去装载,若parent能装载,则返回这个类所对应的Class对象,若
parent不能装载,则由parent的请求者去装载。
如图1所示,loader2的parent为loader1,loader1的parent为system class loader。假设loader2被要求装载
类MyClass,在双亲委派模型下,loader2首先请求loader1代为装载,loader1再请求系统类装载器去装载
MyClass。若系统装载器能成功装载,则将MyClass所对应的Class对象的reference返回给loader1,loader1再
将reference返回给loader2,从而成功将类MyClass装载进虚拟机。若系统类装载器不能装载MyClass,loader1
会尝试装载MyClass,若loader1也不能成功装载,loader2会尝试装载。若所有的parent及loader2本身都不能
装载,则装载失败。
若有一个能成功装载,实际装载的类装载器被称为定义类装载器,所有能成功返回Class对象的装载器(包括定
义类装载器)被称为初始类装载器。如图1所示,假设loader1实际装载了MyClass,则loader1为MyClass的定义
类装载器,loader2和loader1为MyClass的初始类装载器。
需要指出的是,Class Loader是对象,它的父子关系和类的父子关系没有任何关系。一对父子loader可能实例
化自同一个Class,也可能不是,甚至父loader实例化自子类,子loader实例化自父类。假设MyClassLoader继
承自ParentClassLoader,我们可以有如下父子loader:
ClassLoader loader1 = new MyClassLoader();
ClassLoader loader2 = new ParentClassLoader(loader1); //参数 loader1为parent
那么双亲委托模型为什么更安全了?因为在此模型下用户自定义的类装载器不可能装载应该由父亲装载器装载
的可靠类,从而防止不可靠甚至恶意的代码代替由父亲装载器装载的可靠代码。实际上,类装载器的编写者可
以自由选择不用把请求委托给parent,但正如上所说,会带来安全的问题。
4.命名空间及其作用:
每个类装载器有自己的命名空间,命名空间由所有以此装载器为创始类装载器的类组成。不同命名空间的两个
类是不可见的,但只要得到类所对应的Class对象的reference,还是可以访问另一命名空间的类。
例2演示了一个命名空间的类如何使用另一命名空间的类。在例子中,LoaderSample2由系统类装载器装载,
LoaderSample3由自定义的装载器loader负责装载,两个类不在同一命名空间,但LoaderSample2得到了
LoaderSample3所对应的Class对象的reference,所以它可以访问LoaderSampl3中公共的成员(如age)。
例2不同命名空间的类的访问
/*LoaderSample2.java*/
import java.net.*;
import java.lang.reflect.*;
public class LoaderSample2
{
public static void main(String[] args)
{
try
{
String path = System.getProperty("user.dir");
URL[] us = {new URL("file://" + path + "/sub/")};
ClassLoader loader = new URLClassLoader(us);
Class c = loader.loadClass("LoaderSample3");
Object o = c.newInstance();
Field f = c.getField("age");
int age = f.getInt(o);
System.out.println("age is " + age);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/*sub/Loadersample3.java*/
public class LoaderSample3
{
static
{
System.out.println("LoaderSample3 loaded");
}
public int age = 30;
}
编译:javac LoaderSample2.java; javac sub/LoaderSample3.java
运行:java LoaderSample2
LoaderSample3 loaded
age is 30
从运行结果中可以看出,在类LoaderSample2中可以创建处于另一命名空间的类LoaderSample3中的对象并可以
访问其公共成员age。
5.运行时包(runtime package):
由同一类装载器定义装载的属于相同包的类组成了运行时包,决定两个类是不是属于同一个运行时包,不仅要
看它们的包名是否相同,还要看的定义类装载器是否相同。只有属于同一运行时包的类才能互相访问包可见的
类和成员。这样的限制避免了用户自己的代码冒充核心类库的类访问核心类库包可见成员的情况。假设用户自
己定义了一个类java.lang.Yes,并用用户自定义的类装载器装载,由于java.lang.Yes和核心类库java.lang.*
由不同的装载器装载,它们属于不同的运行时包,所以java.lang.Yes不能访问核心类库java.lang中类的包可
见的成员。
6.总结:
在简单讨论了类装载器,双亲委派模型,命名空间,运行时包后,相信大家已经对它们的作用有了一定的了解
。命名空间并没有完全禁止属于不同空间的类的互相访问,双亲委托模型加强了Java的安全,运行时包增加了
对包可见成员的保护。
7.参考资料:
<<Inside The Java Virtual Machine>> by Bill Venners
<<The Java Virtual Machine Specification>> by Sun
四 . 再谈类装载器
作为程序的一部分,每个类都有一个class对象.换言之,每当你编写并且编译了一个新类,就会产生一个
Class对象(更恰当的说,是被保存在一个同名的.class文件中).在运行期,一旦我们想生成这个类的一个对象,运
行这个程序的java虚拟机(JVM)首先检查这个类的Class对象是否已经加载,如果尚未加载,JVM就会根据类名查找
.class文件,并将期载入,所以Java程序并不是一开始执行就被完全加载的,这一点与许多传统语言不同,一旦某
个类的Class对象被载入内存,它就被用来创建这个类的所有对象,请看下面的例子:
class Candy
{
static
{
System.out.println ("Loading Candy");
}
}
class Gum
{
static
{
System.out.println ("Loading Gum");
}
}
class Cookie
{
static
{
System.out.println ("Loading Cookie");
}
}
public class ClassTest
{
public static void main(String[] args)
{
System.out.println ("inside main");
new Candy();
System.out.println ("After creating Candy");
try
{
Class.forName("Gum");
}
catch(ClassNotFoundException e)
{
System.out.println ("Couldn't find Gum");
}
System.out.println ("After Class.forName(\"Gum\")");
new Cookie();
System.out.println ("After creating Cookie");
}
}
打印结果如下:
inside main
Loading Candy
After creating Candy
Couldn't find Gum
After Class.forName("Gum")
Loading Cookie
After creating Cookie
这里的每个类Candy,Gum,Cookie中,都有一个static语句,在类第一次被加载时执行,这时会有相应结果打印出来
告诉我们这个类什么时候被加载了.在main()中,创建对象的代码被置于打印语句之间,以帮助我们判断加载的时
间点.你可以从输出中看出,Class对象仅在需要的时候才被加载,static语句块是在类加载时被执行的.看这行
:Class.forName("Gum"),这是Class类(所有Class对象都属于这个类型)的一个static成员,Class对象和其他对
象一样,我们可以获取并操作它的引用(这就是类加载器的工作),forName()时取得Class对象的引用一个方法,它
时用一个包含目标类的文件名的String作为输入参数,返回一个Class对象的引用,上面的代码忽略了返回值,对
forName()的调用是为了它产生的"副作用":如果类Gum还没有被加载就加载它.在加载的过程中,Gum的static语
句被执行.在前面的例子中,如果Class.forName()找不到你要加载的类.它会抛出异常ClassNotFoundException
发表评论
-
Ubuntu下JDK+Tomcat+MySql环境的搭建
2011-06-15 14:48 1125Ubuntu 下 JDK+Tomcat+MySql ... -
Eclipse下切换 SVN 中已经保存的用户名和密码
2009-09-22 10:28 17051. 把 C:\Documents and Set ... -
Java实现汉字转换为拼音
2006-10-31 13:15 595import java.util.HashMap;import ... -
Java中的克隆(Clone)机制
2007-08-03 09:03 615现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生这个 ... -
JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用简介
2008-12-16 10:32 711在多线程大师Doug Lea的贡献下,在JDK1.5中加入 ... -
Java读取Properties文件的六种方法
2009-04-16 09:34 706使用J2SE API读取Properties文件的六种方法 ... -
深入探讨java集合类
2006-08-24 20:47 694不同的集合在添加对象时的处理是不同的:Set:不允许重复,且没 ... -
递归在java语言中的应用
2006-08-25 09:21 1013一 . 两个小经验 1.在定义一个类时,不要随意定义成员变量 ... -
几个Java基础知识
2006-08-25 19:18 656一 . Hashtable和HashMap Hashtab ... -
面向方面的编程(AOP)
2006-08-25 19:33 710面向对象的编程(OOP)中 ... -
Collection与UML学习
2006-09-01 19:19 675一 . 属性<property>时须注意:1. & ... -
反射和代理
2006-09-01 19:23 691一. 关于数据库.当今的数据处理大致可以分成两大类:联机事务处 ... -
Jdk1.5的新语法和一些java学习的小知识点
2006-09-01 19:30 1199一.1. 操作系统执行具体 ... -
使用DatabaseMetaData和ResultSetMetaData查看数据库信息
2006-10-07 22:26 928/**DatabaseMetaData接口查看数据库的整体综合 ... -
自己动手写数据库连接池
2006-10-07 22:28 1018在前面的文章中已经说过使用连接池的很多好处和优势,也曾讨论过怎 ... -
BASE64编码
2006-10-24 08:39 12981.HttpServletRequest: 请求 ... -
一个实现MD5的简洁的java类
2006-10-28 22:27 632一个实现MD5的简洁的java类 package test; ... -
使用Java将Word转为Html或txt!
2006-10-31 13:47 1203package org.client; // 使用Java将W ... -
理解接口
2006-11-01 14:12 524... -
正则表达式中问号等特殊字符的转义
2006-11-10 00:26 2463正则表达式中问号等特殊字符的转义 除 .$ ^ { [ ( | ...
相关推荐
类装载器学习一、类加载器的基本概念 类装载器学习一、类加载器的基本概念 类装载器学习一、类加载器的基本概念
[浅析J2EE应用服务器的JAVA类装载器]python回朔异常的模块.docx
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java ...
java类装载介绍,介绍了java装载类的先后顺序
类装载器是Java 平台上最神秘,也是最 有趣的一个组,通过类装载器,除了可以实现程序的动态性之外,更能够做 到 无 懈 可 击 的 安 全 性
主要讲述Java的类装载器和命名空间,ClassLoader/parent delegation模型
Java虚拟机类装载的原理及实现
Java类装载过程_.docx
Java虚拟机类装载111.docJava虚拟机类装载111.docJava虚拟机类装载111.doc
类的动态装载机制是JVM的一...本文介绍了JVM中类装载的原理、实现以及应用,尤其分析了ClassLoader的结构、用途以及如何利用自定义 的ClassLoader装载并执行Java类,希望能使读者对JVM中的类装载有一个比较深入的理解。
java jvm类装载器原理 介绍较为详细 大家可以参考
简单的介绍和描述Java虚拟机类装载:原理、实现与应用
本例采用java编写的装载问题,采用的是FIFO队列形式,参考:算法设计与分析
classguard是防止java反编译工具的工具,它允许java类文件使用128bit的AES加密加密。AES密钥是随机生成的每次启动加密工具。解密是一个自定义的类装载器透明地做。这类装载器的主要部分是用C防止反编译等篡改。
摘要通过构建一个能够把Java类装载隔离到一个指定的jar文件中的类装载组件容器框架,你可以确保运行时刻会装载你期望的组件版本。Java的类装载框架强有力且具有灵活性。它允许应用程序存取类库而不必链接到静态的...
java虚拟机装载类的原理,从基础上描述,让我们更清楚底层的运作
java之jvm学习笔记五(实践写自己的类装载器)
Java虚拟机类装载:原理、实现与应用.doc
完整的代码。用java来来写的装载问题。
java算法分析与设计之集装箱装载问题源代码 算法作为计算机专业学生的必修课,同时也是软件开发过程中必备的编程思想,对学习研究计算机专业意义重大;正因为这门课程难,所以除了相关方面的书籍,网络资源少的可怜,...