惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Engineering at Meta
Engineering at Meta
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
B
Blog RSS Feed
GbyAI
GbyAI
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
MyScale Blog
MyScale Blog
D
Docker
阮一峰的网络日志
阮一峰的网络日志
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recorded Future
Recorded Future
美团技术团队
The Register - Security
The Register - Security
V
Visual Studio Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
量子位
B
Blog
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
L
LangChain Blog
Latest news
Latest news
S
SegmentFault 最新的问题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
W
WeLiveSecurity
T
Tenable Blog
T
Tor Project blog

博客园 - yongwnet

项目开发文档格式 JAVA反射实例 java.util.Properties类 jQuery调用WebService详解 产品经理的素质 JAVA 调用 .NET编写的WebService - yongwnet Java中实现鼠标模拟与键盘映射 Win7下轻松注册VS2008 Windows7 下的VPC 浅谈项目管理能力的提升 java多态性详解——父类引用子类对象 Java截取字符串的一些常用处理 extjs COMBOBOX完成类似GOOGLE搜索框(AUTOCOMPLETE) - yongwnet - 博客园 如何有效的压缩VPC虚拟磁盘 VPC 2007 Console界面消失以及解决方法 - yongwnet JAVA匿名实现多线程 - yongwnet - 博客园 java中list类和vector类的比较 JAVA深克隆
java类加载的表现形式
yongwnet · 2010-07-15 · via 博客园 - yongwnet

java中的类是动态加载的,我们先看一下我们常用的类加载方式,先有一个感性的认识,才能进一步

  深入讨论,类加载无非就是下面三种方式。

  class A{}

  class B{}

  class C{}

  public class Loader{

  public static void main(String[] args) throws Exception{

  Class aa=A.class;

  Class bb=Class.forName("B");

  Class cc=ClassLoader.getSystemClassLoader().loadClass("C");

  }

  }

  我们先看.class字面量方式,很多人可能不知道这种方式,因为这种用法不是一般java语法。

  通过javap我们可以发现,这种方式的大致等价于定义了一个静态成员变量

  static Class class$0;(后面的编号是增长的)

  你可以试图再定义一个 static Class class$0,应该会收到一个编译错误(重复定义)。

  Class aa=A.class;

  就相当于

  if(class$0==null){

  try{

  Class.forName("A");

  }

  cacth(ClassNotFoundException e){

  throw new NoClassDefFoundError(e);

  }

  }

  Class aa=class$0;

  可以很清楚的看到,这种类的字面量定义其实不是加载类的方式,而是被编译器处理了,实质上是使用了Class.forName方法,但是使用这种方式有一个很大的好处就是不用处理异常,因为编译器处理的时候如果找不到类会抛出一个NoClassDefFoundError.也许你觉得需要处理 ClassNotFoundException这种异常,事实上99%的情况下我们可以把这种异常认为是一个错误。

  所以大部分情况我们使用这种方式会更简洁。

  最常用的方式就是Class.forName方式了,这也是一个通用的上层调用。这个方法有两个重载,可能很多人都忽略了第二个方法。

  public static Class forName(String name) throws ClassNotFoundException

  public static Class forName(String name, boolean initialize,ClassLoader loader) throws ClassNotFoundException

  第二个方法后面多了两个参数,第二个参数表示是否初始化,第三个参数为指定的类加载器。

  在上面的例子中:

  Class bb=Class.forName("B");

  等价于

  Class bb=Class.forName("B",true,Loader.class.getClassLoader());

  这里要详细说一下这个类的初始化这个参数,如果这个参数为false的话,类中的static成员不会被初始化,static语句块也不会被执行。

  也就是类虽然被加载了,但是没有被初始化,不过在第一次使用时仍然会初始化。

  所以我们有时候会看到Class.forName("XXX")。newInstance()这样的语句,为什么这里要创建一个不用的实例呢?不过是为了保证类被初始化(兼容以前的系统)。

  其实第二个方法是比较难用的,需要指定类加载器,如果不指定而且又没有安装安全管理器的化,是无法加载类的,只要看一下具体的实现就明白了。

  最本质的方式当然是直接使用ClassLoader加载了,所有的类最终都是通过ClassLoader加载的,Class cc=ClassLoader.getSystemClassLoader()。loadClass("C");这里通过使用系统类加载器来加载某个类,很直接的方式,但是很遗憾的是通过这种方式加载类,类是没有被初始化的(也就是初始化被延迟到真正使用的时候)。不过我们也可以借鉴上面的经验,加载后实例化一个对象Class cc=ClassLoader.getSystemClassLoader()。loadClass("C")。newInstance()。

  这里使用了系统类加载器,也是最常用的类加载器,从classpath中寻找要加载的类。

  java中默认有三种类加载器:引导类加载器,扩展类加载器,系统类加载器。

  java中的类加载有着规范的层次结构,如果我们要了解类加载的过程,需要明确知道哪个类被谁加载,某个类加载器加载了哪些类等等,就需要深入理解ClassLoader的本质。

  以上只是类加载的表面的东西,我们还将讨论深层次的东西。