精华内容
下载资源
问答
  • publicstaticSet>getClasses(StringbasePackage){Set>classes=newLinkedHashSet>();StringpackageName=basePackage;StringpackageDirName=packageName.replace('.','/');Enumerationdirs...

    public static Set> getClasses(String basePackage) {

    Set> classes = new LinkedHashSet>();

    String packageName = basePackage;

    String packageDirName = packageName.replace('.', '/');

    Enumeration dirs = null;

    try {

    dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

    while (dirs.hasMoreElements()) {

    URL url = dirs.nextElement();

    String protocol = url.getProtocol();

    if ("file".equals(protocol)) {

    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");

    findClasses(classes, packageName, filePath);

    }

    }

    } catch (IOException e) {

    e.printStackTrace();

    }

    return classes;

    }

    private static void findClasses(Set> classes, String packageName, String packagePath) {

    File dir = new File(packagePath);

    if (!dir.exists() || !dir.isDirectory()) {

    return;

    }

    File[] files = dir.listFiles(new FileFilter() {

    @Override

    public boolean accept(File file) {

    return file.isDirectory() || (file.isFile() && file.getName().endsWith(".class"));

    }

    });

    for (File file : files) {

    if (file.isDirectory()) {

    findClasses(classes, packageName + "." + file.getName(), file.getPath());

    } else {

    String className = file.getName();

    className = className.substring(0, className.length() - 6);

    try {

    ClassLoader loader = Thread.currentThread().getContextClassLoader();

    classes.add(loader.loadClass(packageName + "." + className));

    } catch (ClassNotFoundException e) {

    e.printStackTrace();

    }

    }

    }

    }

    展开全文
  • 楼主想实现一个加载指定应用到gridview上,从网上参考了别人的代码然后改来改去都没能成功,楼主是初学者,java和android都比较薄弱,求各大侠能指点一下loadapps那一段代码要怎么写( ⊙o⊙ ) public class ...
  • 把类加载阶段中的“通过一个类的全限定(博主注:绝对路径)来获取描述此类的二进制字节流”这个动作放在Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块成为”类加载器...

    小引子

    最近做了一个根据同一模块的不同jar版本做同时测试的工具,感觉挺有意思,特此记录。

    类加载器(ClassLoader)是啥?

    把类加载阶段中的“通过一个类的全限定名(博主注:绝对路径)来获取描述此类的二进制字节流”这个动作放在Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块成为”类加载器“。摘自周志明的《深入理解Java虚拟机》

    ClassLoader的用途

    功能测试

    每个加载器,有自己的独立的类名称空间。比较两个类是否”相等“的前提是它们是由同一个类加载加载才有意义,即ClassLoader如果不同,两个类必定不等。这样使得在一个JVM中加载同一个模块的不同版本的jar成为现实,基于反射功能,我们同样可以很轻松实现不同版本的模块测试。本文后面会提供简单demo的实现。

    代码加密

    没有做过,想必是对class文件进行混淆、压缩、native等等手段后的解密过程,这类需求还没遇过。

    OSGi

    是动态模型形同,在eclipse中插件的实现就是基于OSGi思想,而eclipse主要的应用就是插件,所以可以理解为eclipse插件是OSGi的应用典范。做的不多,仅限于了解。

    热部署

    不停止服务,动态替换目标文件。ClassLoader动态加载jar包,如果做一个工程化的东西可能会费些周章,但是原理并不复杂。

    ...

    总之,ClassLoader很重要,Java世界需要它。

    功能测试小样

    本人在本地生成了test1.jar和test2.jar两个jar包。这两个jar都有类com.array7.jvm.classloader.Target,此Demo要实现的是同时将这两个jar包的同名类加载到JVM并且各自执行。

    ** test1.jar Target.java **

    package com.array7.jvm.classloader;

    public class Target {

    public static void main(String[] args) {

    System.out.print("test1");

    }

    }

    ** test2.jar Target.java **

    package com.array7.jvm.classloader;

    public class Target {

    public static void main(String[] args) {

    System.out.print("test2");

    }

    }

    ** TestDriver**

    public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

    ClassLoader loader1 = new URLClassLoader(new URL[]{new URL("file:/home/liushijie/workspace/test/out/artifacts/test1/test1.jar")}, TestDriver.class.getClassLoader());

    ClassLoader loader2 = new URLClassLoader(new URL[]{new URL("file:/home/liushijie/workspace/test/out/artifacts/test2/test2.jar")}, TestDriver.class.getClassLoader());

    String className = "com.array7.jvm.classloader.Target";

    // loader1

    System.out.print("test1.jar \t");

    Class clazz1 = Class.forName(className, true, loader1);

    clazz1.getMethod("main", String[].class).invoke(null, (Object) null);

    System.out.println();

    // loader2

    System.out.print("test2.jar \t");

    Class clazz2 = Class.forName(className, true, loader2);

    clazz2.getMethod("main", String[].class).invoke(null, (Object) null);

    System.out.println();

    System.out.println("实例化后是否相等:" + clazz1.equals(clazz2));

    }

    输出

    test1.jar test1

    test2.jar test2

    实例化后是否相等:false

    其他未提知识点

    ClassLoader的层级关系

    双亲委托与打破

    自定义ClassLoader

    其他参考资料

    展开全文
  • 所以这个过程中就会有参数对应、包名、路径、方法名称等的一致性要求。否则不是找不到方法,就是实例化不了。 还有2种常见的错误 1.java.lang.UnsatisfiedLinkError: no HelloWorld in java....

    使用JNA封装Java映射接口后,由Java程序通过JNI/JNA加载dll库文件调用C接口,出现“java.lang.UnsatisfiedLinkError:包名.类.方法(参数)”问题。

    通过JNI/JNA方式封装映射接口,实际上就是将Java的class文件编译成C语言的xxxx.h头文件,之后根据.h头文件来编写源文件。

    所以这个过程中就会有参数对应、包名、路径、方法名称等的一致性要求。否则不是找不到方法,就是实例化不了。

    还有2种常见的错误

            1. java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path

            2. Exception in thread "main" java.lang.UnsatisfiedLinkError: xxx.xxx.Hello.myprint()V

            错误原因:

    错误1,主要是没有办法path路径中加载。

    错误2,主要是没有myprint方法。

            3 . 如果类库加载没有问题,排除dll本身问题(网上不少人遇到),dll没有问题,加载路径也没有问题,不能连接到方法。这个在命令行的时候不容易发现问题,移到生产环境中容易出现,可能你已经猜到了,就是包路径,类的包路径要和生成头文件类包路径一致。

    展开全文
  • JAVA加载

    2019-12-11 20:42:28
    加载器的主要作用就是根据完全限定,把一个class文件流加载到JVM中,并生成一个与目标类对应的java.lang.Class实例。 JVM提供三种类加载器。启动(bootstrap)类加载器,扩展类加载器,系统类加载器。 一、启动...

    JAVA类加载器

    类加载器的主要作用就是根据完全限定名,把一个class文件流加载到JVM中,并生成一个与目标类对应的java.lang.Class实例。

    JVM提供三种类加载器。启动(bootstrap)类加载器,扩展类加载器,系统类加载器。

    一、启动类加载器

    c++编写,用于加载JAVA_HOME下面的lib库中的jar包,或-Xbootclasspath参数指定的路径下的jar包。并且要符合文件名要求。Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类。

    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            String str = new String();
            System.out.println(str.getClass().getClassLoader());
        }
    }
    

    结果如下:
    null

    二、扩展类加载器

    Java语言实现的,sun.misc.Launcher$ExtClassLoader,它负责加载JRE_HOME/lib/ext目录下或者由系统变量-Djava.ext.dir指定位路径中的类库。

    三、系统类加载器

    java语言实现,sun.misc.Launcher$AppClassLoader,负责加载系统类路径java -classpath或-D java.class.path 指定路径下的类库。是程序中默认的类加载器。

    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            A a = new A();
            System.out.println(a.getClass().getClassLoader());
        }
    }
    

    结果如下:
    sun.misc.Launcher$AppClassLoader@18b4aac2

    四、双亲委派机制。

    如果一个类加载器收到了类加载的请求,那么它首先会把这个请求委托给它的父类加载器去加载,如果父类还有父类加载器,那么进一步向上委托,依次递归。最终将委托到启动类加载器。如果父类加载器可以完成类加载,则成功返回,否则子类加载器自己完成类加载,以此类推。

    好处:1、避免类的重复加载。2、防止核心API被篡改。

    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException
        {
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                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;
            }
        }
    
    五、类加载的锁

    在ClassLoader中的loadClass方法中,首先是使用synchronized关键字进行加锁。
    这里为什么要加锁?主要是为了避免并发加载同名类。
    首先,我们看一下getClassLoadingLock(name)方法,看看加锁对象是什么。

     protected Object getClassLoadingLock(String className) {
            Object lock = this;
            if (parallelLockMap != null) {
                Object newLock = new Object();
                lock = parallelLockMap.putIfAbsent(className, newLock);
                if (lock == null) {
                    lock = newLock;
                }
            }
            return lock;
        }
    

    1、parallelLockMap:是一个CurrentHashMap,主要用来存储(类名,Object实例)的键值对。
    由此可见,加锁对象是一个Object类,与类名绑定,这就使得在加载同名类时只会有一个类加载器进行加载,增加并发能力。
    这里的CurrentHashMap只进不出,如果不停的加载类名不同的类,会使得内存占用越来越大。

    六、类的初始化

    执行classLoader的loadClass之后。(类加载分为加载,连接(验证,准备,解析),初始化),我们可以认为此时完成了解析工作,即在方法区给该类分配了内存,并且把符号引用转化为了直接引用,但是并没有进行初始化。
    **例如:**我们使用系统类加载器的loadClass方法来加载一个自定义的类。可以很容易的看到并没执行类的初始化。

    package reflect;
    
    public class A {
        static{
            System.out.println("aaaaa");
        }
    }
    
    package reflect;
    import sun.misc.Launcher;
    public class Test {
        public static void main(String[] args) throws ClassNotFoundException{
           ClassLoader loader = new Launcher().getClassLoader();
           System.out.println(loader);
           Class<A> clazz = (Class<A>) loader.loadClass("reflect.A");
        }
    }
    

    结果为空,并没有打印“aaaaa”,由此可见,类加载器的loadClass方法并不会触发类的初始化。

    只有在JVM的类加载过程中提到的JVM规范要求的五种类加载时机,才会进行初始化。JVM在进行类的初始化的时候会调用clinit方法。cinit方法即收集所有的static代码并按顺序执行,父类的cinit先于之类的cinit执行。cinit方法是线程安全的。

    七、自定义类加载器

    应用场景:1、从非classpath中加载类。2、加载加密的class文件。

    在JVM中表示两个类是否是同一个类由两个条件,首先是完全限定名一致,然后是类加载器一致。

    隐式加载和显式加载:隐式加载是指不直接通过类加载器加载class文件,而是通过虚拟机自动地把class文件加载到内存中。例如当我们加载一个类,其父类还没有被加载时,就会隐式加载其父类。显示加载是指在代码中调用类加载器加载class文件的情况。例如Class.forName(String name)。

    1. defineClass方法:将一个字节数组转化为Class对象实例。
    protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                             ProtectionDomain protectionDomain)
            throws ClassFormatError
        {
            protectionDomain = preDefineClass(name, protectionDomain);
            String source = defineClassSourceLocation(protectionDomain);
            Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
            postDefineClass(c, protectionDomain);
            return c;
        }
    
    1. loadClass方法:调用父类加载器的loadClass,加载失败则调用自己的findClass方法。(ClassLoader已经实现的方法,实现了双亲委派机制,缓存机制,加锁机制等等)
    2. findClass(name)方法:自定义类加载器实现的方法。

    以下是自定义实现的一个类加载器:
    1、首先定义一个类加载器继承ClassLoader类,并覆盖findClass方法。
    2、读取一个二进制文件并将其转化为字节数组
    3、调用defineClass方法,返回一个Class对象。

    public class MyClassLoader extends ClassLoader{
    
        @Override
        protected Class<?> findClass(String name){
            try {
                FileInputStream in = new FileInputStream(name);
                int len = in.available();
                byte[] bytes = new byte[len];
                in.read(bytes);
                Class clazz = this.defineClass(null,bytes,0,bytes.length);
                return clazz;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
    八、 tomcat的类加载机制

    tomcat官网类加载文档

    1、classpath的概念:
    classpath 是java命令的一项参数,即在java执行class文件时指定的设置。
    -classpath <目录和 zip/jar 文件的类搜索路径>用 ; 分隔的目录, JAR 档案和 ZIP 档案列表, 用于搜索类文件。
    IDEA等编译器在执行java代码的时候,都会调用java命令,并设置相应的classpath参数。

    前面所说,classpath下的jar包或class文件,会被系统类加载器加载。当然系统类加载器也会按照双亲委派机制加载classpath下的这些class文件。

    2、web服务器面临的问题:
    1、部署在同一个服务器上面的两个web应用所使用的类库可以相互隔离。
    2、部署在同一个服务器上面的两个web应用所使用的类库可以共享。
    3、服务器使用的类库应该与应用程序的类库互相独立。

    3、tomcat9的类加载机制
    当tomcat启动时,它会创建以下类加载器,其中父类加载器位于子类加载器的上面。
    在这里插入图片描述

    1. Bootstrap类加载器,相当于上文所提的启动类加载器和扩展类加载器。

    2. System类加载器,系统类加载器,正常情况下用来加载classpath路径下的类。但是在tomcat中,启动脚本 会忽略classpath下的class文件而是从以下库中加载。
      (a)CATALINA_HOME/bin/bootstrap.jar
      (b)CATALINA_BASE/bin/tomcat-juli.jar
      (c)CATALINA_HOME/bin/commons-daemon.jar

    3. Common类加载器,加载tomcat服务器和web应用程序都可见的类。

    4. WebappX 类加载器,每个应用程序的类加载器。加载/WEB-INF/classes 下的class文件以及/WEB-INF/lib 下的jar文件,对于其他应用程序不可见。

    类加载顺序:当应用需要到某个类时,则会按照下面的顺序进行类加载:

    1. 使用bootstrap引导类加载器加载
    2. 使用system系统类加载器加载
    3. 使用应用类加载器在WEB-INF/classes中加载
    4. 使用应用类加载器在WEB-INF/lib中加载
    5. 使用common类加载器在CATALINA_HOME/lib中加载
    展开全文
  • 如果给定类的二进制名称(即为包名加类名的全称),那么类加载器会试图查找或生成构成类定义的数据。一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。java.lang.ClassLoader类的基本职责...
  • 此时需要借助类加载器来帮助完成全限定名 : 包名 + 类名类加载器分为4类 :%JAVA_HOME% : 为JDK设置的环境变量路径. 如环境变量里设置了%java_home%=C:\jdk1.8.01. Bootstrap Classloader : 启动类加...
  • java自定义类加载

    2015-10-02 19:55:01
    1.用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,覆盖他的findClass方法。根据参数指定类的名字,返回对应的Class对象的引用。 http://www.cnblogs.com/chenying99/archive/2013/04/02/2994642.html 2...
  • 这跟web没关系,是java的类加载机制。这个问题是jvm固有的。有这么几种情况:第一种,A和B两个jar都有同一个来自于C的类。但是他们没有用C.jar,而直接把C.jar里的那个类打到A和B里了。根据加载机制,JVM只会加载...
  • JAVA加载体系

    2018-07-13 14:54:26
    一,什么是类加载器 类加载器是将字节码.class... 加载根据一个类的全限定来读取此类的二进制字节流(.class文件)到JVM中,转换为一个与目标类对应的Class对象实例。 验证:确保Class文件字节流中包含信息符...
  • 根据类的全限定名(包名+类名),获取此类的二进制字节流。 虚拟机规范没有指定二进制字节流从哪里读取,可以是class文件,可以是jar,也可以由动态代理在运行时生成,等等,只要是符合规范的字节流即可,由类加载...
  • 根据包名+类名在磁盘种找到这个字节码文件; 创建输入流; 把字节码文件读取到内存; 读到内存后不能随便放,在内存中创建一个java.lang.Class对象保存该类的信息。 假设类中有String型成员,这时候不知道String...
  • 如果给定类的二进制名称(即为包名加类名的全称),那么类加载器会试图查找或生成构成类定义的数据。一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。java.lang.ClassLoader类的基本职责...
  • 加载过程中jvm做了三件事情通过⼀个类的全限定来获取定义此类的⼆进制字节流(class⽂件)在程序运⾏过程中,当要访问⼀个类时,若发现这个类尚未被加载,并满⾜类初始化的条件 时,就根据要被初始化...
  • 加载过程中jvm做了三件事情通过⼀个类的全限定来获取定义此类的⼆进制字节流(class⽂件)在程序运⾏过程中,当要访问⼀个类时,若发现这个类尚未被加载,并满⾜类初始化的条件 时,就根据要被初始化...
  • JAVA-jar

    2019-07-28 15:53:32
    Spi是JAVA提供的一套用来被第三方实现或者扩展的API,spi机制是读取META-INF/services/目录下的元信息,然后ServiceLoader再根据元信息来加载对应的类。Spi规定如下: ①当服务提供者提供了接口的一种具体实现后,...
  • 如果给定类的二进制名称(即为包名加类名的全称),那么类加载器会试图查找或生成构成类定义的数据。一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。java.lang.ClassLoader类的基本职责...
  • java.lang概述(2)

    2019-10-09 09:37:04
    java.lang.ClassLoader该类是Java加载器,负责根据制定的二进制名称加载相应的类。在Java语言规范中规 定,类、接口或原始数据类型有三种命名,他们分别是许可(fullyqualifiedname)、规范(canonicalname)...
  • 1.根据word模板添加书签,例如在标题后需要输入内容的部分定义标签title,然后保存模板到指定文件目录下。 2.java代码 此处用到Spire.Doc.jar,这个在官网Spire.Doc.jar进行下载支持maven和jar两种格式 public ...
  • 可以编译成功,路径也是正确的,可就是报“找不到或无法加载主类”。 其实原因很简单,排除代码拼写错误的情况一般都是以下两个原因引起。...eclipse会自动为文件加入一个包名 package,而按照java的规定我们必须按照包
  •  类的加载机制 类的加载指的是将类的. class文件中的二进制数据读入到内存中....   类加载的过程包括了加载、验证、准备、...1、根据类的全限定名(包名+类名)来获取类的二进制字节流. 2、将类中的所有代表静态数...
  • 问题分析这是由于在运行时类的全名应该是包名+类名,例如在包net.xsoftlab.baike下的类SelfDefineClassLoader的全名应为net.xsoftlab.baike.SelfDefineClassLoader。3.问题的解决java命令后跟类的全名,执行时会...
  • python是一个脚本语言,它不象java一样有一个专门的来处理反射。以 下是我们来看看python是怎么做到类似java一样的反射功能的。我在网上搜了一下,因为在网上没有很明确的文章说要怎么做,所以,我写了这篇,希望 ...
  • 把类加载阶段中的“通过一个类的全限定(博主注:绝对路径)来获取描述此类的二进制字节流”这个动作放在Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块成为”类加载...
  • 问题分析这是由于在运行时类的全名应该是包名+类名,例如在包net.xsoftlab.baike下的类SelfDefineClassLoader的全名应为net.xsoftlab.baike.SelfDefineClassLoader。3.问题的解决java命令后跟类的全名,执行时会...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 294
精华内容 117
关键字:

java根据包名加载

java 订阅