标签: classloader

Parent Last Classloader 解决Java类路径地狱?

我有一个项目使用两个版本的 bouncyCastle jars bcprov-jdk15 和 bcprov-jdk16。jvm 加载旧版本,但我编写的一个功能需要更新版本才能运行。我尝试使用自定义类加载器来解决这个类路径地狱。经过一番谷歌搜索并在以前的一些 Stackoverflow 答案[1] [2]和本博客的帮助下,我编写了以下Parent Last Class loader ,在委托给父类加载器之前从较新的 jar 中加载类。

public class ParentLastClassLoader extends ClassLoader {

    private String jarFile; //Path to the jar file
    private Hashtable classes = new Hashtable(); //used to cache already defined classes

    public ParentLastClassLoader(ClassLoader parent, String path)
    {
        super(parent);
        this.jarFile = path;
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException
    {
        System.out.println("Trying to find");
        throw new ClassNotFoundException();
    }

    @Override
    protected synchronized Class<?> loadClass(String className, boolean …
Run Code Online (Sandbox Code Playgroud)

java bouncycastle classpath classloader

2
推荐指数
1
解决办法
5359
查看次数

Java:当类加载器加载 DLL 时,它们存储在内存中的什么位置?

我的理解是,它们是由 a.dlls加载的,但是它们之后存储在内存中的哪里,并从非静态过程中调用?java.library.pathClassLoaderSystem.loadLibrary()System.load()

JVM内部架构

java memory dll jvm classloader

2
推荐指数
1
解决办法
2969
查看次数

加载使用本机代码的多个版本的 Java 类

如果您想要加载一个类的多个版本,如果它们实现了共享接口并且位于单独的 JAR 中,则可以为每个版本使用单独的类加载器来执行此操作。

如果您有一个调用本机代码的 JAR,则可以将本机代码的共享库 (DLL) 存储在其 JAR 中,方法是将共享库提取到临时文件,然后使用System.load从临时文件加载该库

但如果两者都做,会有效吗?如果两个版本的 JAR 都调用本机代码,并且都包含不同版本的共享库,会发生什么情况?

让我们假设两个 JAR 使用不同的临时文件来存储共享库的副本。但是共享库的两个版本都具有调用具有相同声明的本机 (C) 函数的本机代码(但这些函数的实现不同)。JVM/类加载器/会将System.load Java 代码委托给正确的本机代码吗?或者 JVM 会抱怨名称冲突吗?

如果该方案确实失败,我如何使用使用本机代码的类的多个版本?

java java-native-interface shared-libraries classloader

2
推荐指数
1
解决办法
2759
查看次数

当这些类可能正在使用时,如何成功卸载这些类?

我在我的应用程序中内置了重新加载类的功能。但是,我需要澄清类加载器的行为。

让我解释一下我所知道的,然后提出问题......

我所做的是提供一个由自定义类加载器加载的特殊 jar。然后在 jar 的引导过程中,创建了一堆 spring bean,并且实现某些接口的 bean 被注册以供中央应用程序使用。

现在我在应用程序中启动一个使用这些新类的进程。我可以成功卸载“jar”,更改 jar 中的类并重新加载,然后我就得到了更改。用类加载器的说法来说,卸载意味着使加载类的类加载器无法访问 - 这会导致该类加载器加载的任何类都无法访问,从而有效地卸载。

但是,据我所知,一旦虚拟机加载了该类,它就会将其存储在某个共享空间中,因此不必再次加载它。

我遇到的问题是,有时卸载和重新加载新类不起作用。旧班级仍然存在。按理说,如果我卸载一个类加载器(即使类加载器无法访问)并且该类加载器中的某个类当前正在使用(存在该类型的对象),则无法卸载该类。

这是真的?实践中似乎也是如此。

如果是这样,我如何成功卸载类加载器无法访问时正在使用的类。例如,我可以在每个类上放置一个弱引用,以便我可以检测到类何时无法访问,并在类无法访问时采取行动吗?(但不确定我可以采取什么行动)。

更新响应@Kayaman

我的用例是,我拥有核心应用程序,然后根据客户的要求,我可以加载实现核心应用程序中已知接口的不同类(以便可以访问它们)。然后核心应用程序启动使用这些类的各种进程。这样做的一大优点是,我可以更新这些插件类,而无需进行大量的重新部署,并且每个客户并不需要其中的每一个。当我想加载其中之一的新版本并且当前版本正在使用时,问题就出现了。按理说这是不可能的。

结论

@Kayamam 非常感谢您的咨询。这非常有帮助。这在一定程度上规范了我的想法。结论是,无论我使用什么技术,在虚拟机的现有方式下,您都无法重新加载当前存在强可达对象的类。对于我的一些重新加载,我可以控制这些对象,因为我可以在卸载和重新加载之前使它们无法访问,但对于其他类,我不能这样做......这就是我的问题所在。我需要做的是围住我希望重新加载的类的对象,以便在重新加载这些对象的类时可以暂停使用它们的进程。

java classloader dynamic-class-loaders

2
推荐指数
1
解决办法
5863
查看次数

什么是原始类加载器?在Java中是如何使用的?

我在研究 Java 架构期间,发现了类加载器的概念,它也被称为原始类加载器。我想知道这个类加载器的作用是什么,为什么要用这个?我还想知道我们使用它的基本需求是什么。

java classloader

2
推荐指数
1
解决办法
1154
查看次数

java中class.forName方法的布尔初始化参数

虽然我阅读了文档,但我无法理解加载类时这两行 java codee 之间的区别:

Class<?> cls = Class.forName("jdk.nashorn.api.scripting.ScriptObjectMirror", false, enginClassLoader);


Class<?> cls = Class.forName("jdk.nashorn.api.scripting.ScriptObjectMirror", true, enginClassLoader);
Run Code Online (Sandbox Code Playgroud)

这里的布尔参数在文档中解释如下:

initialize 如果为真,类将被初始化。请参阅 Java 语言规范的第 12.4 节。

就我而言,即使我使用带有 false 参数的代码,它仍然有效。所以我想知道什么时候应该是真的?

java classloader dynamic-class-loaders

2
推荐指数
1
解决办法
550
查看次数

有没有办法取消定义和重新定义类加载器的类?

有没有办法用另一个运行时编译的类来取消定义和重新定义类加载器的类?

java classloader

2
推荐指数
1
解决办法
414
查看次数

在 Java 中,新建或增强类加载器的用例是什么?

在 Java 中,我们知道类加载器是一个 JVM 系统,它将类加载到 JVM 中执行。当我运行一个简单的 Java 类时,它会被运行时系统加载和执行。在这里,我没有对类加载做任何事情。但是我可以看到,有很多项目在编写自定义类加载器或增强现有的类加载器。请让我知道需要类加载器增强或新类加载器的生产时间用例。

java jvm classloader dynamic-class-loaders java-8

2
推荐指数
1
解决办法
71
查看次数

ClassLoader.resolveClass() 实际上做了什么吗?

这是OpenJDK 20+10java.lang.ClassLoader.resolveClass(Class)中的定义:

    protected final void resolveClass(Class<?> c) {
        if (c == null) {
            throw new NullPointerException();
        }
    }
Run Code Online (Sandbox Code Playgroud)

除了检查参数是否非空之外,它似乎什么也没做。然而,文档评论声称:

    /**
     * Links the specified class.  This (misleadingly named) method may be
     * used by a class loader to link a class.  If the class {@code c} has
     * already been linked, then this method simply returns. Otherwise, the
     * class is linked as described in the "Execution" chapter of
     * <cite>The Java Language Specification</cite>.
Run Code Online (Sandbox Code Playgroud)

调用这个方法实际上有什么用处吗?因为它是final,子类不能重写它以使其执行任何不同的操作。它实际上是一个除了空检查之外什么都不做的方法,还是 JVM …

java classloader

2
推荐指数
1
解决办法
553
查看次数

JVM在加载特定类时是否加载所有使用的类?

当JVM加载A类时,它是否加载A中使用的所有类?
而且我想知道导入声明是否对加载过程有某种影响?

JLS的链接将不胜感激.

java classloader jls

1
推荐指数
1
解决办法
1572
查看次数