精华内容
下载资源
问答
  • Java动态加载类

    万次阅读 2018-04-21 09:45:29
    在讲解动态加载类之前呢,我们先弄清楚为什么要动态加载类,静态加载不行吗?我们可以看下面的实例:我在文件夹里写了Office.java 类和 Word.java类,如下:Office.javaclass Office{ public static void main...

    在讲解动态加载类之前呢,我们先弄清楚为什么要动态加载类,静态加载不行吗?我们可以看下面的实例:

    我在文件夹里写了Office.java 类和 Word.java类,如下:


    Office.java

    class Office{
    	public static void main(String[] args){
    		if(args[0].equals("Word")){
    			Word w = new Word();
    			w.start();
    		}
    		if(args[0].equals("Excel")){
    			Excel e = new Excel();
    			e.start();
    		}
    	}
    }

    Word.java

    class Word{
    	public void start(){
    		System.out.println("Word Start");
    	}
    }

    此时我们编译一下Office.java 文件:


    编译会报错,这当然没问题,因为确实没有写Excel.java类。

    但是这个Excel类我们一定会用到吗?如果这个Excel类需要很久才能写出来,在此我们也不能使用其他功能吗?后面如果一个类出问题了,这个系统是不是就瘫痪了?

    所以这就体现出动态加载类的好处了,动态加载类是按需加载的,你需要什么类,就加载什么类,一个类的状态,不会影响到另一个类的使用。

    所以我们可以将Office类改造如下:

    class Office{
    	public static void main(String[] args){
    		try{
    			Class c = Class.forName(args[0]);
    			Word w = (Word)c.newInstance();
    			w.start();
    		}
    		catch(Exception e){
    			e.printStackTrace();
    		}
    		
    	}
    }

    虽然我们还是没有写Excel类,但此时我们再编译Office.java文件,编译通过;

    运行一下:


    成功按照我们预想的结果运行,这样Word类就可以单独运行。

    但是这样还是不够规范,因为现在只能加载Word类类型的类文件,为了使程序有更好的扩展性,我们添加一个接口,只有让所有的功能类实现该接口即可。完善如下:

    OfficeAble.java

    interface OfficeAble{
    	public void start();
    }

    Office.java

    class Office{
    	public static void main(String[] args){
    		try{
    			Class c = Class.forName(args[0]);
    			OfficeAble oa = (OfficeAble)c.newInstance();
    			oa.start();
    		}
    		catch(Exception e){
    			e.printStackTrace();
    		}
    		
    	}
    }

    Word.java

    class Word implements OfficeAble{
    	public void start(){
    		System.out.println("Word Start");
    	}
    }

    这样改造之后,我后面要添加一个Excel类,乃至添加其他的类,只需要实现OfficeAble接口就可以了,不需要改动Office这个类和其他的功能类,扩展性很强,这就是动态加载的优势。

    展开全文
  • java动态加载类和静态加载类

    千次阅读 2016-10-26 16:23:40
    什么是动态加载类 什么是静态加载类 Class.forName 不仅表示类的类类型,还代表了动态加载类。编译时加载是静态加载类, 运行时加载是动态加载类。 请大家区分编译 运行。 二.为何要使用动态加载类 我们写了一个程序...

    一.什么是动态加载类 什么是静态加载类

    Class.forName 不仅表示类的类类型,还代表了动态加载类。编译时加载是静态加载类,

    运行时加载是动态加载类。

    请大家区分编译 运行。

    二.为何要使用动态加载类

    我们写了一个程序 并没有写A类和B类以及start方法 

    public class Main{
    	public static void main(String args[]){
    		if("A".equals(args[0])){
    			A a=new A();
    			a.start();
    		}
    		if("B".equals(args[0])){
    			B b=new B();
    			b.start();
    		}
    	}
    }


    编译:


    我们会发现,我们并不一定用到A功能或B功能,可是编译却不能通过。而在日常的项目中,如果我们写了100个功能,因为一个功能的原因而导致所有功能不能使用,明显使我们不希望的。在这里,为什么会在编译时报错呢?new 是静态加载类,在编译时刻就需要加载所有可能使用到的功能。所以会报错。而在日常中我们希望用到哪个就加载哪个,不用不加载,就需要动态加载类。

    使用动态加载类时,我们不用定义100种功能,只需要通过实现某种标准(实现某个接口)。

    代码:

    public class Main{
    	public static void main(String args[]){
    		try{
    			
    			Class c=Class.forName(args[0]);
    		
    			All a=(All)c.newInstance();
    			a.start();
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    	}
    }
    class A implements All{
    	public void start(){
    		System.out.println("A....START");
    	}
    }
    class B implements All{
    	public void start(){
    		System.out.println("B....START");
    	}
    }
    //接口
    interface All{
    	public void start();
    }


    总结:推荐大家使用动态加载类。原因如上,即节省了代码,又简洁方便,安全。

    学习java反射的时候 看到了这 理解的比较浅显  ,肯定有许多要补充的。慢慢学习 慢慢积累  欢迎评论

    展开全文
  • java类加载之加载类的三种途径

    千次阅读 2019-08-21 12:17:04
    1、由 new 关键字创建一个的实例(静态加载) 在由运行时刻用 new 方法载入 如:Dog dog = new Dog(); 2、调用 Class.forName() 方法 通过反射加载类型,并创建对象实例 如:Class clazz = Class.forName...

    1、由 new 关键字创建一个类的实例(静态加载)
    在由运行时刻用 new 方法载入
    如:Dog dog = new Dog();

    2、调用 Class.forName() 方法
    通过反射加载类型,并创建对象实例
    如:Class clazz = Class.forName(“Dog”);
    Object dog =clazz.newInstance();

    3、调用某个 ClassLoader 实例的 loadClass() 方法
    通过该 ClassLoader 实例的 loadClass() 方法载入。应用程序可以通过继承 ClassLoader 实现自己的类装载器。
    如:Class clazz = classLoader.loadClass(“Dog”);
    Object dog =clazz.newInstance();

    三者的区别:

    1和2使用的类加载器是相同的,都是当前类加载器。(即:this.getClass.getClassLoader)。
    3由用户指定类加载器。如果需要在当前类路径以外寻找类,则只能采用第3种方式。第3种方式加载的类与当前类分属不同的命名空间。
    另外:
    1是静态加载,2、3是动态加载

    两个异常(exception):

    • 静态加载的时候如果在运行环境中找不到要初始化的类,抛出的是NoClassDefFoundError,它在JAVA的异常体系中是一个Error

    • 动态态加载的时候如果在运行环境中找不到要初始化的类,抛出的是ClassNotFoundException,它在JAVA的异常体系中是一个checked异常

    Class.forName与ClassLoader.loadClass区别

    Class的装载包括3个步骤:加载(loading),连接(link),初始化(initialize).
    Class.forName(className)实际上是调用Class.forName(className, true, this.getClass().getClassLoader())。第二个参数,是指Class被loading后是不是必须被初始化。
    ClassLoader.loadClass(className)实际上调用的是ClassLoader.loadClass(name, false),第二个参数指Class是否被link。
    Class.forName(className)装载的class已经被初始化,而ClassLoader.loadClass(className)装载的class还没有被link。一般情况下,这两个方法效果一样,都能装载Class。但如果程序依赖于Class是否被初始化,就必须用Class.forName(name)了。
    例如,在JDBC编程中,常看到这样的用法,Class.forName(“com.mysql.jdbc.Driver”).
    如果换成了getClass().getClassLoader().loadClass(“com.mysql.jdbc.Driver”),就不行。
    com.mysql.jdbc.Driver的源代码如下:
    // Register ourselves with the DriverManager
    static {
    try {
    java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
    throw new RuntimeException(“Can’t register driver!”);
    }
    }
    原来,Driver在static块中会注册自己到java.sql.DriverManager。而static块就是在Class的初始化中被执行。
    所以这个地方就只能用Class.forName(className)。

    对于相同的类,JVM最多会载入一次。但如果同一个class文件被不同的ClassLoader载入,那么载入后的两个类是完全不同的。因为已被加载的类由该类的类加载器实例与该类的全路径名的组合标识。设有 packagename.A Class ,分别被类加载器 CL1 和 CL2 加载,所以系统中有两个不同的 java.lang.Class 实例: <CL1, packagename.A> 和 <CL2, packagename.A>。

    classload过程
    https://www.cnblogs.com/gdpuzxs/p/7044963.html
    https://blog.csdn.net/javazejian/article/details/73413292#编写自己的类加载器
    jar包导入项目,启动后classnotfound:
    -jar 后面所跟的jar包的优先级别最高。如果指定了-jar选项,所有环境变量和命令行制定的搜索路径都将被忽略。JVM APPClassloader将只会以jar包为搜索范围
    https://www.cnblogs.com/zpbolgs/p/7267384.html
    https://blog.csdn.net/sayyy/article/details/81120749
    3、MANIFEST文件
    https://www.jb51.net/article/131101.htm

    展开全文
  • JVM启动、加载类过程 下面我将定义一个非常简单的java程序并运行它,来逐步分析java虚拟机启动的过程。 package org.luanlouis.jvm.load; import sun.security.pkcs11.P11Util; /** * Crea...

    本文参考自“《Java虚拟机原理图解》5. JVM类加载器机制与类加载过程 ”,对原内容作了些修改并重新组织

    JVM启动、加载类过程

    下面我将定义一个非常简单的java程序并运行它,来逐步分析java虚拟机启动的过程。

    package org.luanlouis.jvm.load;  
    import sun.security.pkcs11.P11Util;  
    
    /** 
     * Created by louis on 2016/1/16. 
     */  
    public class Main{  
        public static void main(String[] args) {  
            System.out.println("Hello,World!");  
            ClassLoader loader = P11Util.class.getClassLoader();  
            System.out.println(loader);  
        }  
    }  
    1. 根据JVM内存配置要求,为JVM申请特定大小的内存空间;

      JVM启动时按照其配置要求,申请一块内存,并根据JVM规范和实现将内存划分为几个区域。class二进制文件信息被放入“方法区”,对象实例被放入“java堆”等。关于JVM内存模型内容参考 JVM(一)JVM内存模型

    2. 创建一个引导类加载器实例,初步加载系统类到内存方法区区域中;

      JVM申请好内存空间后,JVM会创建一个引导类加载器(Bootstrap Classloader)实例,引导类加载器是使用C++语言实现的,负责加载JVM虚拟机运行时所需的基本系统级别的类,如java.lang.String, java.lang.Object等等。
      引导类加载器(Bootstrap Classloader)会读取{JRE_HOME}/lib下的jar包和配置,然后将这些系统类加载到方法区内。

      引导类加载器将类信息加载到方法区中,以特定方式组织,对于某一个特定的类而言,在方法区中它应该有 运行时常量池、类型信息、字段信息、方法信息、类加载器的引用,对应class实例的引用等信息。

    3. 创建JVM 启动器实例 Launcher,并取得类加载器 ClassLoader

      此时,JVM虚拟机调用已经加载在方法区的类sun.misc.Launcher 的静态方法 getLauncher(), 获取 sun.misc.Launcher 实例

    4. 使用上述获取的 ClassLoader 实例加载我们定义的类;

      通过 launcher.getClassLoader() 方法返回 AppClassLoader 实例,接着就是 AppClassLoader 加载 我们自定义类.

      加载自己写的类之前先要加载我们写的类中用到的其他类。在 org.luanlouis.jvm.load.Main 类被编译成的class文件中有一个叫常量池(Constant Pool)的结构体,通过这个常量池中的 CONSTANT_CLASS_INFO 常量判断该class用到了哪些类,并通过类加载器去加载这些类。

    5. 加载完成时候JVM会执行Main类的main方法入口,执行Main类的main方法;

    6. 结束,java程序运行结束,JVM销毁。

    类加载器

    • 类加载器的作用:通过一个类的全限定名来获取描述此类的二进制字节流,并将此类相关信息加载到JVM的方法区,并创建一个 java.lang.Class 对象作为此类的访问接口, class 对象的引用也保存在方法区内。
    • 每一个类加载器都有独立的类名称空间。比较两个类是否相等的前提是两个类是由同一个类加载器加载的,否则两个类比不相等。

    从JVM角度来讲,只有两种类加载器:启动类加载器其他的类加载器。因为前者是JVM虚拟机的一部分,后者是独立于JVM实现的。

    更细致一点划分,类加载器分为下面三种:

    1. 启动类加载器(Bootstrap ClassLoader)

    启动类加载器是使用C++语言实现的(HotSpot),负责加载JVM虚拟机运行时所需的基本系统级别的类,如java.lang.String, java.lang.Object等等。
    启动类加载器(Bootstrap Classloader)会读取 {JRE_HOME}/lib 下的jar包(如 rt.jar)和配置,然后将这些系统类加载到方法区内。
    由于类加载器是使用平台相关的底层C/C++语言实现的, 所以该加载器不能被Java代码访问到。但是,我们可以查询某个类是否被引导类加载器加载过。

    2. 扩展类加载器 (Extension ClassLoader)

    此加载器由 sun.misc.Launcher$ExtClassLoader 实现,它负责加载 {JAVA_HOME}\lib\ext 目录下的类库, 开发者可以直接获取此加载器。
    拓展类加载器是是整个JVM加载器的Java代码可以访问到的类加载器的最顶端,即是超级父加载器,拓展类加载器是没有父类加载器的。

    3. 应用程序加载器 (Application ClassLoader)

    此加载器负责加载用户类路径上指定的类库,若没有指定自定义加载器,则此加载器一般是程序中默认的加载器。
    应用类加载器将拓展类加载器当成自己的父类加载器。

    4. 用户自定义类加载器(Customized Class Loader)

    用户可以自己定义类加载器来加载类。所有的类加载器都要继承 java.lang.ClassLoader 类并重写 findClass(String name) 方法。用户自定义类加载器默认父加载器是 应用程序加载器

    各个类加载器关系如下:

    双亲委派模型

    双亲委派模型工作过程:一个类加载器收到类加载的请求,它首先会把这个请求委派给父类加载器去完成,层层上升,只有当父类加载器无法完成此加载请求时,子加载器才会尝试自己去加载。

    要注意的是父加载器和子加载器的关系不是继承关系而是组合关系。子加载器中有一个私有属性 parent 指向父加载器。

    具体到上述三个加载器时:当应用程序加载器尝试加载类的时候,首先尝试让其父加载器–拓展类加载器加载;如果拓展类加载器加载成功,则直接返回加载结果 Class<T> instance , 加载失败,则会询问是否引导类加载器已经加载了该类;只有没有加载的时候,应用类加载器才会尝试自己加载。

    从源码看双亲委派模型:

    public Class<?> loadClass(String name) throws ClassNotFoundException {  
        return loadClass(name, false);  
    }  
    
    protected Class<?> loadClass(String name, boolean resolve)  
        throws ClassNotFoundException  
    {  
        synchronized (getClassLoadingLock(name)) {  
            // 首先,检查是否已经被当前的类加载器加载,如果已经被加载,直接返回对应的Class<T>实例  
            Class<?> c = findLoadedClass(name);  
                //初次加载  
                if (c == null) {  
                long t0 = System.nanoTime();  
                try {  
                    if (parent != null) {  
                        //如果有父类加载器,则先让父类加载器加载  
                        c = parent.loadClass(name, false);  
                    } else {  
                        // 没有父加载器,则查看是否已经被启动类加载器加载,有则直接返回  
                        c = findBootstrapClassOrNull(name);  
                    }  
                } catch (ClassNotFoundException e) {  
                    // ClassNotFoundException thrown if class not found  
                    // from the non-null parent class loader  
                }  
                // 父加载器加载失败,并且没有被引导类加载器加载,则尝试自己加载  
                if (c == null) {  
                    // If still not found, then invoke findClass in order  
                    // to find the class.  
                    long t1 = System.nanoTime();  
                    // 自己尝试加载  
                    c = findClass(name);  
    
                    // this is the defining class loader; record the stats  
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);  
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);  
                    sun.misc.PerfCounter.getFindClasses().increment();  
                }  
            }  
            //是否解析类   
            if (resolve) {  
                resolveClass(c);  
            }  
            return c;  
        }  
    } 

    应用程序加载器一般流程如下:

    展开全文
  • springboot-启动加载类

    千次阅读 2019-04-13 15:14:17
    项目在启动的时候做一些初始化工作,需要实现ApplicationRunner接口,并重写run()方法,当项目启动时,run()方法便会自动执行。 package com.wps.education.runner;...import org.springframework.boot.Applic...
  • 什么是动态加载类 什么是静态加载类Class.forName 不仅表示类的类类型,还代表了动态加载类。编译时加载是静态加载类,运行时加载是动态加载类。请大家区分编译 运行。二.为何要使用动态加载类我们写了一个程序 并...
  • python 动态加载类和函数的方法

    千次阅读 2019-07-19 18:43:04
    python 动态加载类和函数的方法 用到的python 函数 glob.glob()glob:文件名模式匹配,可以用通配符类筛选文件名。 __import__()函数用于动态加载模块 。如果一个模块经常变化就可以使用该方法来动态载入。 getattr...
  • 如何配置 tomcat 的 context.xml 文件以实现无需重启服务器,自动重新加载修改过的文件。
  • 如何在spring 容器中动态加载类

    千次阅读 2019-06-17 18:19:51
    思路是启动一个线程然后动态加载类获取类的注解,并用拿到的注解对象和注解对象对比,问题是:用main方式直接启动线程拿到的注解对象和注解类对比是相等的,但是用spring 容器注解启动后发现两者不相等。以下是截图...
  • 因为在编译的时候,加载类是静态加载,运行时加载是动态加载。 在此我对反射有了如下的理解: 如果有一个class A,可以使用new A()来创建对象,但如果要使用字符串"A"来创建class A的对象,在Java中通过...
  • 我现在用xml传以下字段到服务器:class是的完整名称,action是要调用的方法名,para的子元素是方法形参,data的子元素是方法实参。 ``` <user><class>...
  • JAVA动态加载类和静态加载类

    千次阅读 2015-07-28 17:21:54
    1.JAVA动态加载类和静态加载类的区别  new创建对象的方式称作为静态加载,而使用Class.forName("XXX")称作为动态加载,它们俩本质的区别在于静态加载的类的源程序在编译时期加载(必须存在),而动态加载的类在编译...
  • idea找不到或无法加载类

    千次阅读 2019-03-17 21:18:53
    解决办法1,jdk变量设置 2,删除modules(一般都是这个问题) 最后点击加号重新添加模块
  • spring加载类的顺序

    千次阅读 2018-05-16 11:18:25
    spring @Order标记order标签是用来指定加载bean的顺序,数字越小越先加载。其中的spring的xml配置文件,内容完善一下。在使用标签&lt;context:component-scan/&gt;的情况下,是不需要&lt;context:...
  • Java中加载类并不一定初始化

    千次阅读 2019-06-25 19:04:13
    一、加载类不初始化的情况 Test.class.getClassLoader().loadClass("Student"); Class clazz = Student.class; 这两种情况下,加载类,但是不会“链接“和”初始化” 通过命令:java -verbose:class test查看类加载...
  • Java运行时动态加载类之ClassLoader

    千次阅读 2017-03-22 17:13:20
    需求场景:动态加载类ClassLoaderd,在xml文件中配置加载类名称和方法,: 一、准备 1)在D:\\tmp\\目录下配置a.xml文件: say add 2)要动态加载的类: package dx; public class map { ...
  • 加载类的原理机制是怎么样的?答:很多人都不是很清楚java的class类什么时候加载在运行内存中,其实类加载的时间是发生在一下几种情况:1.实例化对象时,就像spring管理的bean一样,在tomcat启动时就实例化了bean...
  • JAVA虚拟机加载类到运行过程总结

    千次阅读 2017-07-27 00:27:34
    ,由sun.misc.Launcher$AppClassLoader实现,负责加载用户路径classpath上所指定的类库,是类加载器ClassLoader中的getSystemClassLoader()方法的返回值,开发者可以直接使用应用程序类加载器,如果程序中没有...
  • java如何通过类加载器加载类和jar包

    千次阅读 2017-12-03 16:00:19
     把项目中要用到的class文件和jar放到D:\loader\terry\codex目录下,如何让项目通过代码的方式实现加载和使用这些呢? 方案:通过URLClassLoader构造D:\loader\terry\codex这个路径下的类加载器,在通过Java...
  • 解决IDEA run()时找不到加载类的问题

    千次阅读 2017-11-20 11:02:34
    在class处打断点debug可以看出,已经连接到了VM,但是在路径下找不到该文件,打出错误信息:【错误:找不到加载类aaa.bbb】,然后断开VM连接。 1.确认本机中java是否安装,安装路径是否正确。相关命令:java 、java...
  • Spring启动后加载类或启动类方法

    万次阅读 2014-07-22 19:54:34
    Spring容器启动后会加载,没有指定其他参数,则Spring容器默认通过JavaBean的无参构造函数加载。类比,也可以通过指定构造函数的参数,调用特定的含参构造函数。 那如果是指定某个方法呢,则使用配置init...
  • 手动加载类的两种方法

    千次阅读 2015-06-06 15:06:06
    手动加载类有两种方式,Class.forName()和ClassLoader.loadClass()两种,到底有什么区别呢?  通俗的讲,Class.forName()会初始化,即会执行被加载类的static块,ClassLoader.loadClass()则不会。由于在JDBC连接...
  • 为什么使用自动加载? 在以后编写代码时,有的时候需要做一个新增功能,上传功能,表单验证功能这个时候引入文件是一件非常头疼的事情,那么针对这件头疼的事情如何处理,今天由郝先生带各位一块了解一下? 1.以前...
  • 深入理解Java类加载器(ClassLoader)

    万次阅读 多人点赞 2017-06-26 09:34:08
    在JDK1.2之前,在自定义类加载时,总会去继承ClassLoader类并重写loadClass方法,从而实现自定义的类加载类,但是在JDK1.2之后已不再建议用户去覆盖loadClass()方法,而是建议把自定义的类加载逻辑写在findClass()...
  • JVM类加载类的分类

    千次阅读 2020-09-10 20:20:43
    JVM类加载类的分类 虚拟机自带的加载器 启动类加载器(引导类加载器,Bootstrap ClassLoader) 这个类加载使用C/C++语言实现的,嵌套在JVM内部。 它用来加载Java中的核心库((JAVA_HOME/jre/lib/rt.jar、...
  • 需求场景是:通过ClassLoader动态加载外部class文件,class文件又依赖某个具体jar包,需要动态加载jar包,采用URLClassLoader。 1、xml配置文件 ETLEnc.jar say 放在D:\\tmp\\目录下; 2、User....
  • Android 强大的图片加载类 图库效果

    千次下载 热门讨论 2014-08-11 00:40:54
    代码为博客实例代码:http://blog.csdn.net/lmj623565791/article/details/38476887 有问题博客中留言
  • Java应用环境中不同的class分别由不同的ClassLoader负责加载。 一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ...负责加载java基础,主要是 %JRE_HOME/lib/ 目录下的rt
  • JVM教你怎么类加载

    万次阅读 2020-03-02 20:47:38
    类加载
  • java 动态加载类

    千次阅读 2017-02-23 18:42:35
    一、什么是动态加载类动态加载:通过Class.forName的方式来得到一个Class类型的实例,然后通过这个Class类型的实例的newInstance来初始化,这种方法我们称之为动态加载程序在运行时调用相应方法,即使其他方法是错误...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,753,202
精华内容 701,280
关键字:

加载类