java - JVM 在启动时锁定 JAR 文件

标签 java jvm classloader javassist

我已经实现了一个自定义类加载器,它是通过系统属性-Djava.system.class.loader=com.MyClassLoader设置的。 CL 包含一个静态初始化程序,它调用一些代码(在加载任何类之前),使用 javassist 库操作 jar(maven 依赖项)内的类文件的字节代码。这工作正常,除了我无法用新的 jar 替换旧的 jar,因为 JVM 正在锁定文件并且仅在它终止时释放它。这是为什么?如何强制 JVM 释放锁?

这是一个小代码片段:

public class CustomClassLoader extends ClassLoader {

static {
   ...
   modifyJar();
}

private static void modifyJar(){        
   URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
    URL[] urls = urlClassLoader.getURLs();
    for(URL url : urls) {
      //find matching jar and modify byte code
    }        
    replaceJarFile(metaData);
}

private static void replaceJarFile(JarMetaData jmd){
     //add modified class to new jar file
     JarFile jar = new JarFile(jmd.getJarFile());
     ...

    //this method call returns false, jar is locked by another process (the JVM)
    if(oldJarFile.delete()){
       ...
    }  
  }
}

操作系统:Windows 10

JDK版本:1.8.0_131

最佳答案

从未指定应该可以更改 JVM 使用的 jar。而且 JVM 已经安静地锁定了 jar 很长一段时间。更改正在使用的 jar 中的类也会带来语义问题,即如何处理对已加载的类的修改,甚至是正在进行的类加载与写入重叠。

由于修改 jar 将是永久性更改,因此最合理的方法是在启动 JVM 之前执行此操作,例如在不同的 JVM 中。

但是,如果您想即时更改类定义,则应该编写一个 Java 代理。对于那些支持 Java 代理的 JVM,Instrumentation API提供所需的一切,例如在加载时转换类,甚至重新定义已加载的类。
它还提供了一种将 jar 文件添加到 Bootstrap 或系统类路径的标准方法,而假设应用程序类加载器是 URLClassLoader 的子类,则在 Java 9 中将开始失败。

关于java - JVM 在启动时锁定 JAR 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48176931/

相关文章:

java - 我可以通过配置 java.policy 文件来拒绝对 jvm 类的访问吗?

osgi - 为什么导入的类优先于捆绑类?

java - Spring Boot内容类型 'multipart/form-data;boundary=--------------------------#;charset=UTF-8'不支持

java - 如何解决java中的NoSuchAlgorithmException?

java - 在没有 RMI 或套接字的情况下如何让两个 JVM 进行通信?

Java 无效的最大堆大小

java - 如何使用纳秒在 phpmyadmin 中创建时间线?

java - 如何从jsp文件中调用java文件中带参数的函数?

java - 如何使用 Java 以编程方式安装所有 Java JVM(不是默认的)?

java - 用于部署和测试的 Maven 类路径生成