类加载
所有类加载器,都是ClassLoader的子类。
类加载器永远以.class运行的目录为准。
读取classpath根目录下的文件有以下几种方式:
1 在Java项目中可以通过以下方式获取classspath下的文件:
public void abc(){ //每一种读取方法,使用某个类获取Appclassloader ClassLoader cl = ReadFile.class.getClassLoader(); URL url = cl.getResource("a.txt"); System.err.println("url1 is:"+url.getPath()); //第二种方式,直接使用ClassLoader URL url2 = ClassLoader.getSystemResource("a.txt"); System.err.println("url2 is:"+url2.getPath()); }
在Tomcat中tomcat又声明了两个类载器:
StandardClassLoader– 加载tomcat/lib/*.jar - serlvetapi.jar
Webappclassloader /加载 tomcat/webapps/project/web-inf/lib/*.jar && web-inf/classes/*.class
在任何的项目中,获取类的加载器都应该使用以下方式:
SomeClass(你写的).class.getClassLoader().getResource ;获取到这个类的类加载器
在java项目中是:AppClassLoader
在Web项目中:WebAppClassLoader
测试父类加载器:
public class OneServlet extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ClassLoader loader = OneServlet.class.getClassLoader();//WebAppClassLoader int index=1; while(loader!=null){ System.err.println((index++)+"类加载器是:"+loader.getClass()); loader=loader.getParent();//获取父类加载器 } } }
运行的结果:
1类加载器是:class org.apache.catalina.loader.WebappClassLoader 2类加载器是:class org.apache.catalina.loader.StandardClassLoader 3类加载器是:class sun.misc.Launcher$AppClassLoader 4类加载器是:class sun.misc.Launcher$ExtClassLoader
自定义类加载器
JDK以哪一个类加载器读取A类的字节码,则A类就是被哪一个类加载器加载 的。
一个同名的类,是否可以相互转换,要看是否是在同个类加载器中。
package cn.hx.demo; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; public class MyClassLoader2 extends ClassLoader { /** * name:cn.itcast.demo.Person * 根据包名找到.class文件 * cn.itcast.demo.person = > cn/itcast/demo/Person.class */ public Class<?> findClass(String name ) throws ClassNotFoundException { String classNameWithPackage=name; Class<?> cls = null; try { //先将 name = name.replace(".","/"); name +=".class"; //确定目录 URL url = MyClassLoader2.class.getClassLoader().getResource(name); System.err.println(">>:"+url.getPath()); File file = new File(url.getPath()); InputStream in = new FileInputStream(file); //读取这个.class文件的字节码 byte[] b = new byte[in.available()];//直接声明这个字节大小为这个文件的大小 int len = in.read(b);//len=621 System.err.println(len); /** * 第一个参数是类名 */ cls = defineClass(classNameWithPackage,b,0,len); } catch (Exception e) { e.printStackTrace(); } return cls; } }
测试类自定义类加载器
public class ClassLoaderDemo { public static void main(String[] args) throws Exception { MyClassLoader2 mc = new MyClassLoader2(); Class cls = mc.findClass("cn.itcast.demo.Person"); Object o = cls.newInstance(); System.err.println("toString:"+o+","+o.getClass().getClassLoader()); //直接使用peron是 AppClassLoader System.err.println(">>:"+Person.class.getClassLoader()); //由于o是由mc加载的。而Person是由App加载的,所有不可以转换=来自于两个不同的加载器 //Person p = (Person) o;//类型转换错误ClassCastException //System.err.println(p); } }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持小牛知识库!
我试图修改几个类的字节代码,这些类的打包jar文件不在类路径中-它们是在给定URL的运行时由自定义的加载的。我尝试使用和来拦截那些类,但失败了。类加载器是遗留项目的一部分,因此我无法直接对其进行更改。 代理可以很好地处理AppClassLoader“本地”加载的类,但只会忽略那些由自定义类加载器加载的类。 CustomClassLoader: 我的代理中使用的ClassFileTransforme
我一直在Java玩简单的自定义类加载器,到目前为止,对于非模块相关的类来说,一切都按照预期工作。但是,我似乎找不到任何方法来使用我的类加载器从模块加载类,即使与模块相关的方法已经被重载。我尝试做的是从模块“HelloModularWorld”加载一个类,并运行它的main。然而,当我指定包所在的目录时,它将“正常”加载,并报告为在未命名模块中。我错过了什么? 类加载器只是从文件系统的其他地方加载类
问题内容: 我一直在尝试建立一个自定义的类加载器,该类加载器将拦截类以打印出哪些类正在加载到应用程序中。类加载器看起来像这样 它只是吐出它加载的所有类的名称。但是,当我尝试运行一些代码时, 通过 它打印出来 这似乎很奇怪。这不是一个简单的类,它取决于程序包中的许多其他类。这些类显然正在加载中,因为d python代码能够执行操作并读取我的文件。但是,由于某些原因,那些类并未由load的类加载器加载
一、类加载机制 1.定义: 把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。 在Java语言里,类型的加载、连接和初始化过程都是在程序运行期间完成的,这种策略虽然会令类加载时稍微增加一些性能开销,但是会为Java应用程序提供高度的灵活性,Java里天生可以动态扩展的语言特性就是依赖运行期动态加载和动态连接这个特点来实现的。
本文向大家介绍classloader类加载器_基于java类的加载方式详解,包括了classloader类加载器_基于java类的加载方式详解的使用技巧和注意事项,需要的朋友参考一下 基础概念 Classloader 类加载器,用来加载 Java 类到 Java 虚拟机中。与普通程序不同的是。Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVM(Java虚拟机
问题内容: 我试图列出Java类加载器加载类的顺序。如果我使用参数,它将列出它加载的每个接口/类,包括大量接口,如Serializable,异常等。是否有方法可以调整此输出,因此它仅显示在我的main方法定义的类中加载了哪些类? 问题答案: 我猜您最好的选择是执行以下操作: 一旦方法开始并且结束之前,输出一些固定的文本。 将 详细 输出通过管道传输到文件中 使用 less 或 grep 之类的东西