全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Java classloader和namespace详细介绍

Java classloader和namespace详细介绍

  Java虚拟机通过装载、连接和初始化一个JAVA类型,使该类型可以被正在运行的JAVA程序所使用。其中,装载就是把二进制形式的JAVA类型读入JAVA虚拟机中。连接就是把这种已经读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去。连接阶段分为三个步骤-验证、准备和解析。验证确保了JAVA类型数据格式正确并适于JAVA虚拟机使用。准备负责为该类分配它所需的内存,比如为它的类变量分配内存。解析把常量池中的符号引用转换为直接引用,如内存地址指针。在初始化期间,激活类的静态变量的初始化代码和静态代码块。

  装载步骤的最终产品是一个被装载类型的Class类的实例对象,它成为JAVA程序与内部数据结构之间的接口。对于每一个被装载的类型,虚拟机都会相应地为它创建一个Class类的实例。

1 类装载器的安全作用

  JAVA类装载器在JAVA安全体系结构中起着最关重要的作用,是JAVA安全沙箱的第一道防线。类装载器体系结构在三个方面对JAVA的沙箱起作用:

1) 它防止恶意代码去干涉善意的代码
2) 它守护了被信任的类库的边界
3) 它将代码归入某类(称为保护域),该类确定了代码可以进行哪些操作。

类装载器体系结构可以防止恶意代码去干涉善意的代码,这是通过为不同的类装载器装入的类提供不同的命名空间来实现的。

2双亲委派模型

  JAVA虚拟机规范定义了两种类型的类装载器-启动类装载器和用户自定义类装载器,启动类装载器是JAVA虚拟机实现的一部分,通过继承ClassLoader类,用户可以创建自定义的类装载器来完成特定要求的加载。JAVA虚拟机已经创建了2个自定义类装载器-扩展类装载器和系统类装载器。
每一个用户自定义的类装载器在创建时被分配一个“双亲”parent类装载器。如果没有显示地传递一个双亲类装载器给用户自定义的类装载器的构造方法,系统类装载器就默认被指定为双亲。如果传递到构造方法的是一个已有的用户自定义类装载器的引用,该用户自定义类装载器就作为双亲;如果向构造方法传递了null,启动类装载器就是双亲。
启动类装载器Bootstrap Classloader:它是JAVA虚拟机实现的一部分,是c/c++实现的,它没有双亲。启动类装载器装载JAVA核心库代码。

扩展类装载器Extension Classloader:继承自URLClassLoader,初始化向构造方法传递了null,所以双亲是Bootstrap Classloaser。它从java.ext.dirs扩展目录中装载代码。

系统类装载器Application Classloader:继承自URLClassLoader,双亲是Extension Classloaser。它从CLASSPATH路径中装载应用程序代码。

其中,网络类装载器URLClassLoader是JAVA库提供的一个类装载器,用来从网络其他位置装载类。

双亲孩子类装载器委派链

  在双亲委派模型下,当一个装载器被请求装载某个类时,它首先委托自己的双亲parent去装载,若parent能装载,则返回这个类所对应的Class对象,若parent不能装载,则由parent的请求者去装载。

现在假设要求Cindy去装载一个名为java.io.FileReader的类型。Cindy第一件事情就是去找Mom来装载那个类型;Mom所做的第一件事情就是去找Grandma来装载那个类型;而Grandma首先去找启动类装载器去装载。在这个例子中,启动类装载器可以装载那个类型,它就返回代表java.io.FileReader的Class实例给Grandma。Grandma传递该Class的引用 Mom,Mom再回传给Cindy,Cindy返回给程序。

 

  在此模型下,启动类装载器可以抢在扩展类装载器之前去装载类,而扩展类装载器可以抢在系统类装载器之前去装载那个类,系统类装载器又可以抢在网络类装载器之前去装载它。这样,使用双亲-孩子委派链的方式,启动类装载器会在最可信的类库-核心Java API-中首先检查每个被装载的类型,然后,才依次到扩展路径、系统类路径中检查被装载的类型文件。用这种方法,类装载器的体系结构就可以防止不可靠的代码用它们自己的版本来替代可以信任的类。

3命名空间 

由不同的类装载器装载的类将被放在虚拟机内部的不同命名空间。命名空间由一系列唯一的名称组成,每一个被装载的类有一个名字。JAVA虚拟机为每一个类装载器维护一个名字空间。例如,一旦JAVA虚拟机将一个名为Volcano的类装入一个特定的命名空间,它就不能再装载名为Valcano的其他类到相同的命名空间了。可以把多个Valcano类装入一个JAVA虚拟机中,因为可以通过创建多个类装载器从而在一个JAVA应用程序中创建多个命名空间。

1)  初始类装载器/ 定义类装载器

命名空间有助于安全的实现,因为你可以有效地在装入了不同命名空间的类之间设置一个防护罩。在JAVA虚拟机中,在同一个命名空间内的类可以直接进行交互,而不同的命名空间中的类甚至不能觉察彼此的存在,除非显示地提供了允许它们进行交互的机制,如获取Class对象的引用后使用反射来访问。

  如果要求某个类装载器去装载一个类型,但是却返回了其他类装载器装载的类型,这种装载器被称为是那个类型的初始类装载器 ;而实际装载那个类型的类装载器被称为该类型的定义类装载器 。任何被要求装载类型,并且能够返回Class实例的引用代表这个类型的类装载器,都是这个类型的初始类装载器。在上面的一个例子中,java.io.FileReader定义类装载器是启动类装载器,Cindy、Mom、Grandma、启动类装载器都是初始类装载器。

  虚拟机会为每一个类装载器维护一张列表,列表中是已经被请求过的类型的名字。这些列表包含了每一个类装载器被标记为初始类装载器的类型,它们代表了每一个类装载器的命名空间。虚拟机总是会在调用loadClass()之前检查这个内部列表,如果这个类装载器已经被标记为是这个具有该全限定名的类型的初始类装载器,就会返回表示这个类型的Class实例,这样,虚拟机永远不会自动在同一个用户自定义类装载器上调用同一个名字的类型两次。

2) 命名空间的类型共享

  前面提到过只有同一个命名空间内的类才可以直接进行交互,但是我们经常在由用户自定义类装载器定义的类型中直接使用Java API类,这不是矛盾了吗?这是类型共享 原因-如果某个类装载器把类型装载的任务委派给另外一个类装载器,而后者定义了这个类型,那么被委派的类装载器装载的这个类型,在所有被标记为该类型的初始类装载器的命名空间中共享。
例如上面的例子中,Cindy可以共享Mon、Grandma、启动类装载器的命名空间中的类型,Kenny也可以共享 Mon、Grandma、启动类装载器的 命名空间中的 类型,但是Cindy和Kenny的命名空间不能共享。

3) 运行时包

  每个类装载器都有自己的命名空间,其中维护着由它装载的类型。所以一个JAVA程序可以多次装载具有同一个全限定名的多个类型。这样一个类型的全限定名就不足以确定在一个JAVA虚拟机中的唯一性。因此,当多个类装载器都装载了同名的类型时,为了唯一表示该类型,还要在类型名称前加上装载该类型的类装载器来表示-[classloader class]。
  在允许两个类型之间对包内可见的成员进行访问前,虚拟机不但要确定这个两个类型属于同一个包,还必须确认它们属于同一个运行时包-它们必须有同一个类装载器装载的。这样,java.lang.Virus和来自核心的java.lang的类不属于同一个运行时包,java.lang.Virus就不能访问JAVA API的java.lang包中的包内可见的成员。

4自定义类装载器

  JAVA类型要么由启动类装载器装载,要么通过用户自定义的类装载器装载。启动类装载器是虚拟机实现的一部分,它以与实现无关的方式装载类型,JAVA提供了抽象类java.lang.ClassLoader,用户自定义的类装载器是类ClassLoader的子类实例,它以定制的方式装载类。所有用户自定义类装载器都实例化自ClassLoader的子类。
下面提供一个简单的用户自定义类装载器。

import java.io.*; 
public class UserDefinedClassLoader extends ClassLoader 
{ 
 private String directory = "d:/classes/"; 
 private String extensionType = ".class"; 
  
 public UserDefinedClassLoader() 
 { 
  super(); // this set the parent as the AppClassLoader by default 
 } 
  
 public UserDefinedClassLoader( ClassLoader parent ) 
 { 
  super( parent ); 
 } 
  
 public Class findClass( String name ) 
 { 
  byte[] data = loadClassData( name ); 
   
  return defineClass( name, data, 0, data.length ); 
 } 
  
 private byte[] loadClassData( String name ) 
 { 
  byte[] data = null; 
  try 
  { 
   FileInputStream in = new FileInputStream( new File( directory + name.replace( '.', '/') + extensionType ) ); 
   ByteArrayOutputStream out = new ByteArrayOutputStream(); 
   int ch = 0; 
    
   while( ( ch = in.read() ) != -1 ) 
   { 
    out.write( ch ); 
   } 
    
   data = out.toByteArray(); 
  } 
  catch ( IOException e ) 
  { 
   e.printStackTrace(); 
  } 
  return data; 
 } 
} 
 


public class Valcano 
{ 
 static 
 { 
  System.out.println("Valcano Class Initialized");  
 } 
  
 public Valcano() 
 { 
 } 
} 
public class ClassLoaderTest 
{ 
 public static void main( String[] args ) 
 { 
  try 
  { 
   UserDefinedClassLoader userLoader = new UserDefinedClassLoader(); 
   Class valcanoClass1 = userLoader.loadClass( "Valcano" ); 
    
   URL url = new URL("file:/d:/classes/" ); 
   ClassLoader urlLoader = new URLClassLoader( new URL[] { url } ); 
   Class valcanoClass2 = urlLoader.loadClass( "Valcano" ); 
   System.out.println( "valcanoClass1 classloaer = " + valcanoClass1.getClassLoader() ); 
   System.out.println( "valcanoClass2 classloaer = " + valcanoClass2.getClassLoader() ); 
    
   System.out.println( "valcanoClass1 = valcanoClass2 ? " + ( valcanoClass1 == valcanoClass2 ) ); 
  } 
  catch( Exception e ) 
  { 
   e.printStackTrace(); 
  } 
 } 
} 

输出结果:

valcanoClass1 classloaer = UserDefinedClassLoader@1fb8ee3
valcanoClass2 classloaer = java.NET.URLClassLoader@14318bb
valcanoClass1 = valcanoClass2 ? false

我们可以看到,有两个不同的Valcano的Class实例被加载到同一个虚拟机中。

另外我们看到Valcano类静态初始化语句没有被执行,意味着类没有被初始化,这是因为JAVA中只有当类被主动使用时类型才会进行初始化。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


# Java  # classloader和namespace  # classloader和namespace详解  # Java基础之ClassLoader详解  # java自定义ClassLoader加载指定的class文件操作  # jvm之java类加载机制和类加载器(ClassLoader)的用法  # Java类加载器ClassLoader用法解析  # Java运行时环境之ClassLoader类加载机制详解  # Java Classloader机制用法代码解析  # Java中ClassLoader类加载学习总结  # classloader类加载器_基于java类的加载方式详解  # java ClassLoader机制详细讲解  # 深入解析Java中的Classloader的运行机制  # Java源码解析之ClassLoader  # 自定义  # 多个  # 自己的  # 机中  # 去找  # 都是  # 这是  # 子类  # 会在  # 被称为  # 它就  # 它以  # 应用程序  # 恶意代码  # 第一件  # 的是  # 是一个  # 类库  # 加载  # 就会 


相关文章: 已有域名和空间如何快速搭建网站?  专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?  如何用AWS免费套餐快速搭建高效网站?  网站微信制作软件,如何制作微信链接?  如何获取上海专业网站定制建站电话?  如何选择建站程序?包含哪些必备功能与类型?  如何在阿里云虚拟服务器快速搭建网站?  建站主机系统SEO优化与智能配置核心关键词操作指南  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  建站主机如何选?高性价比方案全解析  如何高效搭建专业期货交易平台网站?  建站三合一如何选?哪家性价比更高?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  C++用Dijkstra(迪杰斯特拉)算法求最短路径  香港服务器如何优化才能显著提升网站加载速度?  如何选择高性价比服务器搭建个人网站?  建站之星上传入口如何快速找到?  建站主机默认首页配置指南:核心功能与访问路径优化  PHP正则匹配日期和时间(时间戳转换)的实例代码  营销式网站制作方案,销售哪个网站招聘效果最好?  宝塔建站助手安装配置与建站模板使用全流程解析  深圳企业网站制作设计,在深圳如何网上全流程注册公司?  如何正确下载安装西数主机建站助手?  建站主机与服务器功能差异如何区分?  ui设计制作网站有哪些,手机UI设计网址吗?  如何选择网络建站服务器?高效建站必看指南  制作网站的基本流程,设计网站的软件是什么?  建站之星安装后界面空白如何解决?  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  c# 在ASP.NET Core中管理和取消后台任务  网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?  如何挑选高效建站主机与优质域名?  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  在线制作视频的网站有哪些,电脑如何制作视频短片?  实例解析Array和String方法  如何用美橙互联一键搭建多站合一网站?  如何快速查询网址的建站时间与历史轨迹?  台州网站建设制作公司,浙江手机无犯罪记录证明怎么开?  如何在IIS中新建站点并解决端口绑定冲突?  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  赚钱网站制作软件,建一个网站怎样才能赚钱?是如何盈利的?  无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?  太原网站制作公司有哪些,网约车营运证查询官网?  网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?  官网自助建站系统:SEO优化+多语言支持,快速搭建专业网站  哈尔滨网站建设策划,哈尔滨电工证查询网站?  如何在搬瓦工VPS快速搭建网站?  ,购物网站怎么盈利呢?  相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?  如何解决ASP生成WAP建站中文乱码问题? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。