`
christ_man
  • 浏览: 5586 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

URLClassloader

 
阅读更多

 简要介绍一下urlClassloader  的作用。一般我们在开发中会经常用自已的方式加载与管理类。特别是在设计一套系统时。urlClassloader是一个不错的选择。他实现了从硬盘上以绝对路径的方式加载类。tomcat,jboss底层就采用了这样的方式来管理与加载自身的类。如tomcat api jar 等。在tomcat7中。urlClassloader是作为配置加载类的一部分存在的,他不仅仅加载单个class,他还可以加载一个jar.如下实例让我们来认识一下urlClassloader. 这里只是初探。

 


 

 

HelloWorld 类

 

public class HelloWorld
{
  public String sayHello(String s)
  {
      return s + " : helloWorld!!!";  
  }
  public static void main(String []args) 
  {
     System.out.println("HelloWorld");
  }
}

 

TClassLoader 类

 

public class TClassLoader
{
   public String [] getArray(int m)
   {
       if(m <= 0)
       {
           return null;
       }
       String iStr[] = new String[m];
       for(int i=0; i<m; i++ )
       {
          iStr[i] = "a" + i;
       }
       return iStr;
   }
}

 

将上述两个类通过控制台或eclipse打包成jar文件。分别放在某个盘符的某个目录下。

 

接下来就是一个测试类。来实现jar的装载与调用。

 

 

package com.taobao.util;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Set;

public class ClassLoaderUtil extends URLClassLoader {

 public ClassLoaderUtil(URL [] reposities) {
  // TODO Auto-generated constructor stub
  super(reposities);
 }
 
 public ClassLoaderUtil(URL [] reposities , ClassLoader parent)
 {
  super(reposities,parent);
 }
 
 
 public static void main(String []args) throws Exception 
 {
  //自定义UrlClassLoader
  
  ClassLoaderUtil util = null;
  
  String urls[] = new String[]{"E:/urlclassloader/hello/HelloWorld.jar","E:/urlclassloader/tclass/TClassLoader.jar"};
  
  Set<URL> s = new HashSet<URL>();
  
  for(int i=0; i<urls.length; i++)
  {
   File f = new File(urls[i]);
   f = new File(f.getCanonicalPath());
   if(!f.exists() && !f.canRead())
   {
    continue;
   }
   URL url = f.toURI().toURL();
   s.add(url);
  }
  URL [] u = s.toArray(new URL[s.size()]);
  util = new ClassLoaderUtil(u);
  
  Class class1 = util.loadClass("HelloWorld");
  Object ojava = class1.newInstance();
  Method method = class1.getMethod("sayHello", new Class[]{String.class});
  System.out.println(method.invoke(ojava, new Object[]{"abc"}));
  
  System.out.println(ClassLoaderUtil.class.getClassLoader());
  
  
 }
}

 

---------------------------------------------------------------------------------------------------------------------------------

 

  1. 读取配置文件中的信息

 

配置文件的内容:

用URLClassLoader读配置文件内容:

[java] view plaincopy
  1. import java.io.IOException;  
  2. import java.net.URL;  
  3. import java.net.URLClassLoader;  
  4. import java.util.Properties;  
  5.   
  6. public class Testext {  
  7.     public static void main(String[] args) throws IOException {  
  8.         Properties properties = new Properties();  
  9.         URL[] urls = new URL[] { new URL("file:/"  
  10.                 + System.getProperty("user.dir") + "/ravageWeb/") };  
  11.         URLClassLoader ucl = new URLClassLoader(urls);  
  12.         //ClassLoader cl = Testext.class.getClassLoader();  //这两行也可以不写  
  13.         //cl = ucl;     //如果写,下面就要改为:cl.getResourceAsStream...  
  14.         properties.load(ucl.getResourceAsStream("resources/testpro.properties"));  
  15.         System.out.println(properties.getProperty("sui"));  
  16.     }  
  17. }  

遇到的问题:1. "/ravageWeb/" 中第二个 / 可写可不写。 但是若改为 "/ravageWeb/resources/" 则resources后必须加 /  否则报NullPointerException

              用ClassLoader读配置文件内容:

[html] view plaincopy
  1. import java.io.IOException;  
  2. import java.util.Properties;  
  3.   
  4. public class Testext {  
  5.     public static void main(String[] args) throws IOException {  
  6.         Properties properties = new Properties();  
  7.         properties.load(Testext.class.getClassLoader()  
  8.                 .getResourceAsStream("resources/testpro.properties"));  
  9.         System.out.println(properties.getProperty("sui"));  
  10.     }  
  11. }  

 

总结:很显然ClassLoader与URLClassLoader的区别是:

ClassLoader只能读位于classpath下的文件(即:resources/testpro.properties必须放到src目录下,编译后进入bin目录);

而URLClassLoader可以读任意目录下的文件!

       2. 载入一个类

用ClassLoader载入一个类:

[html] view plaincopy
  1. import java.io.IOException;  
  2.   
  3. public class Testext {  
  4.     public static void main(String[] args) throws IOException,  
  5.             ClassNotFoundException {  
  6.         Class c = Testext.class.getClassLoader().loadClass("stalk.STalkClient");  
  7.         System.out.println(c.getName());    //输出:stalk.STalkClient  
  8.     }  
  9. }  


 

用URLClassLoader载入一个类:

[html] view plaincopy
  1. import java.io.IOException;  
  2. import java.net.URL;  
  3. import java.net.URLClassLoader;  
  4.   
  5. public class Testext {  
  6.     public static void main(String[] args) throws IOException,  
  7.             ClassNotFoundException {  
  8.           
  9.         URL[] urls = new URL[] { new URL("file:/"  
  10.                 + System.getProperty("user.dir") + "/ravageWeb/") };  
  11.         URLClassLoader ucl = new URLClassLoader(urls);  
  12.         Class c = ucl.loadClass("NoPackage");  
  13.         System.out.println(c.getName());  
  14.     }  
  15. }  


遇到的问题:"/ravageWeb/" 中第二个 /  必须写,否则报ClassNotFoundException

 

总结:

ClassLoader只能load位于classpath(src目录)下的类;

而URLClassLoader可以load任意目录下的类!

 

----------------------------------------------------------------------------------------------------------------------------------

我们知道,Java利用ClassLoader将类载入内存,并且在同一应用中,可以有很多个ClassLoader,通过委派机制,把装载的任务传递给上级的装载器的,依次类推,直到启动类装载器(没有上级类装载器)。如果启动类装载器能够装载这个类,那么它会首先装载。如果不能,则往下传递。当父类为null时,JVM内置的类(称为:bootstrap class loader)就会充当父类。想想眼下的越来越多用XML文件做配置文件或者是描述符、部署符。其实这些通过XML文档描述的配置信息最终都要变成 Java类,基实都是通过ClassLoader来完成的。URLClassLoader是ClassLoader的子类,它用于从指向 JAR 文件和目录的 URL 的搜索路径加载类和资源。也就是说,通过URLClassLoader就可以加载指定jar中的class到内存中。 

 

下面来看一个例子,在该例子中,我们要完成的工作是利用URLClassLoader加载jar并运行其中的类的某个方法。

 

首先我们定义一个接口,使所有继承它的类都必须实现action方法,如下:

 

public interface ActionInterface {

     public String action();

完成后将其打包为testInterface.jar文件。

 

接下来新建一工程,为了编译通过,引入之前打好的testInterface.jar包。并创建TestAction类,使它实现 ActionInterface接口。如下:

 

 

public class  TestAction implements ActionInterface {

    public  String action() {

         return " com.mxjava.TestAction.action " ;

    } 

 

完成后将其打包为test.jar,放在c盘根目录下。下面要做的就是利用URLClassLoader加载并运行TestAction的action方法,并将返回的值打印在控制台上。

 

新建一工程,引入testInterface.jar包。并创建一可执行类(main方法),在其中加入如下代码:

 

URL url = new URL(“file:C: / test.jar”);

URLClassLoader myClassLoader  =   new  URLClassLoader( new  URL[]   { url } );

Class myClass  =  myClassLoader.loadClass(“com.mxjava.TestAction”);

ActionInterface action  =  (ActionInterface)myClass.newInstance();

System.out.println(action.action()); 

  在上面的例子中,首先利用URLClassLoader加载了C:/test.jar包,将其中的com.mxjava.TestAction类载入内存,将其强制转型为testInterface包中的ActionInterface类型,最后调用其action方法,并打印到控制台中。

 

  执行程序后,在控制台上如期打印出我们想要的内容。但是,事情并没有那么简单,当我们将该代码移动web应用中时,就会抛出异常。原来,Java为我们提供了三种可选择的ClassLoader:

1. 系统类加载器或叫作应用类加载器 (system classloader or application classloader)

2. 当前类加载器

3. 当前线程类加载器

 

  在上例中我们使用javac命令来运行该程序,这时候使用的是系统类加载器 (system classloader)。这个类加载器处理 -classpath下的类加载工作,可以通过ClassLoader.getSystemClassLoader()方法调用。 ClassLoader 下所有的 getSystemXXX()的静态方法都是通过这个方法定义的。在代码中,应该尽量少地调用这个方法,以其它的类加载器作为代理。否则代码将只能工作在简单的命令行应用中。当在web应用中时,服务器也是利用ClassLoader来加载class的,由于ClassLoader的不同,所以在强制转型时JVM认定不是同一类型。(在JAVA中,一个类用其完全匹配类名(fully qualified class name)作为标识,这里指的完全匹配类名包括包名和类名。但在JVM中一个类用其全名和一个加载类ClassLoader的实例作为唯一标识。因此,如果一个名为Pg的包中,有一个名为Cl的类,被类加载器KlassLoader的一个实例kl1加载,Cl的实例,即C1.class在JVM中表示为 (Cl, Pg, kl1)。这意味着两个类加载器的实例(Cl, Pg, kl1) 和 (Cl, Pg, kl2)是不同的,被它们所加载的类也因此完全不同,互不兼容的。)为了能够使程序正确运行,我们首要解决的问题就是,如何将 URLClassLoader加载的类,同当前ClassLoader保持在同一类加载器中。解决方法很简单,利用java提供的第三种 ClassLoader—当前线程类加载器即可。jdk api文档就会发现,URLClassLoader提供了三种构造方式:

 

 // 使用默认的委托父 ClassLoader 为指定的 URL 构造一个新 URLClassLoader。  

 URLClassLoader(URL[] urls) 

 // 为给定的 URL 构造新 URLClassLoader。  

 URLClassLoader(URL[] urls, ClassLoader parent) 

 // 为指定的 URL、父类加载器和 URLStreamHandlerFactory 创建新 URLClassLoader。 

 URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory)  

接下来要做的就是,在构造URLClassLoader时,将当前线程类加载器置入即可。如下:

 

  URLClassLoader myClassLoader  =   new  URLClassLoader( new  URL[]   { url } , Thread.currentThread().getContextClassLoader()); 

总结:

  Java是利用ClassLoader来加载类到内存的,ClassLoader本身是用java语言写的,所以我们可以扩展自己的 ClassLoader。利用URLClassLoader可以加载指定jar包中的类到内存。在命行上利用URLClassLoader加载jar时,是使用系统类加载器来加载class的,所以在web环境下,就会出错。这是因为JVM中一个类用其全名和一个加载类ClassLoader的实例作为唯一标识的。我们只要利用URLClassLoader的第二种构造方法并传入当前线程类加载器即可解决。

 

分享到:
评论

相关推荐

    Java URLClassLoader动态加载jar包1

    Java URLClassLoader 是Java标准库中的一个类加载器,它允许我们动态地从指定的URL位置加载类和资源。这个功能在开发插件系统、热部署或者处理多种版本库的场景中非常有用。从JDK 1.2开始,`java.net.URLClassLoader...

    使用URLClassLoader加载本地文件夹c盘下的test.jar文件

    URLClassLoader是Java提供的一种类加载器,它允许我们通过URL来加载类和资源,从而实现这一目标。本篇文章将深入讲解如何使用URLClassLoader加载C盘下的test.jar文件。 首先,了解类加载器的基本概念。在Java中,类...

    URLClassLoader中指定目录和jar的问题

    在Java编程语言中,`URLClassLoader`是Java标准类加载器的一种实现,它负责从指定的URL(统一资源定位符)加载类和资源。本文将深入探讨`URLClassLoader`的工作原理,以及如何处理指定目录和JAR文件中的类加载问题。...

    java反序列化漏洞URLClassLoader利用1

    这里提到的“Java反序列化漏洞URLClassLoader利用1”是利用了Java中的`java.net.URLClassLoader`来远程加载并执行恶意代码的一个示例。 `URLClassLoader`是Java中的一个类加载器,它可以从指定的URL列表中加载类。...

    URLClassLoader初体验

    在Java世界中,`URLClassLoader`是一个非常关键的类,它是`ClassLoader`的子类,主要用于从指定的URL(统一资源定位符)加载类和资源。这篇博客文章“URLClassLoader初体验”可能深入探讨了如何使用`URLClassLoader`...

    Springboot + Hutool-db 使用 URLClassLoader 动态加载外部数据库和数据池 jar包实例

    在这个场景中,我们看到一个基于Springboot的应用程序结合了Hutool-db库,利用URLClassLoader来实现动态加载外部数据库驱动和数据池的jar包。这使得开发者可以在不重启应用的情况下更新或添加新的数据库连接和资源池...

    ClassLoaderTest:测试如何正确关闭类加载器,以便可以关闭基础jar文件上的文件句柄

    当我们使用自定义的URLClassLoader时,尤其需要注意类加载器的生命周期管理,因为不正确的关闭可能导致打开的文件句柄无法正确释放,从而消耗系统资源。 首先,我们来了解下类加载器的工作原理。Java中的类加载器...

    java动态加载插件化编程详解

    3. URLClassLoader:URLClassLoader是一个Java类加载器,它可以根据URL加载类或 jar 文件。在插件化编程中,URLClassLoader可以用于加载插件。 4. 插件管理:插件管理是指对插件的生命周期管理,包括插件的加载、...

    aop面向切面需要的jar包

    at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang....

    lassLoader的关系以及如何防止ClassLoader内存泄漏

    在Java世界中,类加载器(ClassLoader)是关键的组件之一,它负责将类的字节码文件(.class)从文件系统或网络中加载到Java虚拟机(JVM)中,使得程序能够运行。本篇文章将深入探讨ClassLoader的关系网络以及如何...

    URLClass工程之间反射机制的实现

    `URLClassLoader`是Java中的一个关键类,它是`ClassLoader`的一个子类,主要用于加载来自特定URL位置的类。在"URLClass工程之间反射机制的实现"这个主题中,我们将深入探讨如何利用这两个概念在不同的工程之间实现...

    swing-worker-1.1.jar

    at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(NativeMethod) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at sun.misc....

    java 反射运行时加载外部jar到Tomcat StandardClassLoader1

    URLClassLoader c = (URLClassLoader) getClass().getClassLoader().getParent().getParent(); ``` 2. 创建一个 `URL` 对象,表示要加载的 JAR 文件的 URL。 ```java URL jar = new URL(...

    AXMLPrinter2、baksmali、smali、dex2jar

    at java.net.URLClassLoader.defineClass(Unknown Source) at java.net.URLClassLoader.access$100(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController....

    android反编译dex2jar

    at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang....

    解决classloader的jar包

    包括commons-logging commons-beanutils commons-lang ezmorph json-lib-2.4-jdk15 commons-collections-3.2.1的jar包,可以解决 org/apache/commons/lang/exception/NestableRuntimeException的问题

    RMI不依赖其他http服务实现代码动态下载

    这个改进的核心在于Java 6中的`java.net.URLClassLoader`和`sun.rmi.server.LoaderHandler`类。`URLClassLoader`能够从URL加载类,而`LoaderHandler`则负责处理RMI中的类加载逻辑。通过这两者的结合,RMI可以在需要...

    详解Java动态加载数据库驱动

    `getConnection` 方法接收一个数据源名称,然后根据名称获取相应的数据源信息,如果还没有加载对应驱动,则使用 `URLClassLoader` 加载驱动类,实例化 `Driver` 对象,并将其注册到 `DriverManager` 中。最后,使用...

    反射获取jar文件中的类

    URLClassLoader myClassLoader = new URLClassLoader(new URL[]{url1}, Thread.currentThread().getContextClassLoader()); String ppName = sName.replace("/", ".").replace(".class", ""); Class myClass = ...

    Spring bean 动态注册,jar包热替换

    Spring bean 一般通过配置文件和注解进行加载,如果要实现jar或class文件,动态实现spring bean 的动态加载,并通过UrlClassLoader完成jar和class文件的加载。可以实现jar的热替换。spring的bean动态加载则需要对...

Global site tag (gtag.js) - Google Analytics