设为首页 加入收藏

TOP

关于Class对象、类加载机制、虚拟机运行时的内存布局的全面解析和推测(二)
2017-10-10 12:31:24 】 浏览:8261
Tags:关于 Class 对象 加载 机制 虚拟 行时 内存 布局 全面 解析 推测
port java.net.URL; import java.net.URLClassLoader; public class MyClassLoader extends ClassLoader { private String path; @Override public Class<?> findClass(String name){ byte[] data = null; try { data = loadClassData(path); } catch (IOException e) { e.printStackTrace(); } return defineClass(name, data, 0, data.length); } private byte[] loadClassData(String path) throws IOException{ File f = new File(path); FileInputStream fis = new FileInputStream(f); byte[] data = new byte[(int) f.length()]; fis.read(data); fis.close(); return data; } /* * 定义了带两个参数的loadClass方法,为了多传递一个path参数 * 内部一定要调用父类的loadClass方法,因为该方法内实现了双亲委派模型 */ public Class<?> loadClass(String path, String name) throws ClassNotFoundException{ this.path = path; return super.loadClass(name); } public static void main(String[] args) throws ClassNotFoundException{ MyClassLoader mcl = new MyClassLoader(); /*打印当前类加载器的父加载器*/ System.out.println(mcl.getParent()); System.out.println("=========="); Class<?> cls1 = mcl.loadClass("D:/用户目录/我的文档/Eclipse/Person.class" ,"javalearning.Person"); System.out.println(cls1.getClassLoader()); System.out.println("=========="); Class<?> cls2 = mcl.loadClass(null, "java.lang.Thread"); System.out.println(cls2.getClassLoader()); System.out.println("=========="); } }

 

通过代码实现可以看出,自定义类加载器的核心精髓是调用ClassLoader类中的defineClass方法。

 

下面是运行结果

sun.misc.Launcher$AppClassLoader@4e0e2f2a
==========
demo.MyClassLoader@2a139a55
==========
null
==========

 

从运行结果看出,MyClassLoader的父加载器是AppClassLoader(这是在ClassLoader的构造函数中实现的)。Person.Class由MyClassLoader加载(父类加载器都没有加载成功),而当MyClassLoader加载String.class时,委托到BootstrapClassLoader加载,发现BootstrapClassLoader已加载完毕,结果null表示String类的加载器是BootstrapClassLoader。

 

Person类

package javalearning;
public class Person{
	public int age;
	public String name;
	
	public Person(){
		name = "zx";
		age = 18;
	}
	
	@Override
	public String toString(){
		return name +" "+ age;
	}
}

 

2. 谈谈java.lang.Class和java.lang.Object之间的悖论

通过java的语法学习,我们知道以下三点

1)java.lang.Class类继承java.lang.Object类

2)按照语法规则,创建一个java.lang.Class对象必须先创建它的父类(java.lang.Object)的一个对象

3)按照语法规则,创建一个类的对象,必须先存在表示该类的java.lang.Class对象

但是这三点又是矛盾的。这两个对象的创建没有办法顺序实现。所以不是先创建好一个,再创建另一个,而是通过自举实现的,也就是说是两个对象同时创建好。自举程序本身不是由Java语言实现的,而是由C和C++实现的。

所有的java.lang.Class对象的创建不是通过构造函数创建的,而是通过加载器生成的。每个类都有对应的用于反射该类的Class对象,每个类有且只对应一个Class对象。

每一个类都从Object类中继承了一个getClass的实例方法,返回该类对应的Class对象。

Class.class对象有两层含义。第一,它是一个Class类的实例。第二,它又又表示是Class类本身用于反射的对象,所以该对象的getClass方法返回它本身。我们不能通过Class.class的newInstance方法产生Class类的实例,如果这么做,会抛出异常。另一个方面,假设能够产生这样的对象,我们怎么知道这个对象应该对应哪一个类呢?

 

3. 谈谈java.lang.Class和类加载器之间的悖论

类加载器也是一个类,也有对应的Class对象,但是Class对象又必须通过加载器的实例产生,显然这两点又是矛盾的。

三个默认的类加载器中ExtensionClassLoader和AppClassLoader是由java代码实现的,而BootstrapClassLoader是由C/C++实现的。也就是说BootstrapClassLoader没有,不需要有,也不可能有对应Class对象。ExtensionClassLoader类的实例和它对应ExtensionClassLoader.class对象都是由BootstrapClassLoader一并加载创建完成。然后再由ExtensionClassLoader对象加载AppC

首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇设计模式精要 下一篇没有了

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目