簡體   English   中英

如何訪問 WEB-INF/lib/jars?

[英]How to get access to WEB-INF/lib/ jars?

我有 Gradle 項目與Spring BootAspectJ

想要直接從 WEB-INF/libs 動態加載aspectjweaverspring-instrument javaagents(其中 Spring 引導找到所有依賴項)

Gradle 依賴:

在此處輸入圖像描述

代理加載器:

public class AgentLoader {

private static final Logger LOGGER = LoggerFactory.getLogger(AgentLoader.class);

public static void loadJavaAgent() {
    if (!isAspectJAgentLoaded()) {
        LOGGER.warn("Aspect agent was not loaded!");
    }
}

public static boolean isAspectJAgentLoaded() {
    try {
        Agent.getInstrumentation();
    } catch (NoClassDefFoundError e) {
        return false;
    } catch (UnsupportedOperationException e) {
        LOGGER.info("Dynamically load AspectJAgent");
        return dynamicallyLoadAspectJAgent();
    }
    return true;
}

public static boolean dynamicallyLoadAspectJAgent() {
    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
    int p = nameOfRunningVM.indexOf('@');
    String pid = nameOfRunningVM.substring(0, p);
    try {
        VirtualMachine vm = VirtualMachine.attach(pid);
        String jarFilePath = AgentLoader.class.getClassLoader().getResource("WEB-INF/libs/aspectjweaver-1.9.6.jar").toString();
        vm.loadAgent(jarFilePath);
        jarFilePath = AgentLoader.class.getClassLoader().getResource("WEB-INF/libs/spring-instrument-5.3.2.jar").toString();
        vm.loadAgent(jarFilePath);
        vm.detach();
    } catch (Exception e) {
        LOGGER.error("Exception while attaching agent", e);
        return false;
    }
    return true;
 }
}

但是發現nullgetResource()的返回值

處理此問題的最佳解決方案是什么?

尼基塔,今天是你的幸運日。 I just had a moment and was curious how to make my code snippet from https://www.eclipse.org/aspectj/doc/released/README-187.html , which obviously you found before, work in the context of Spring Boot . 我剛剛使用了我的 Maven Spring 引導操場項目。 Depending on which Java version you are using, you either need to make sure that tools.jar from JDK 8 is defined as a system-scoped dependency and also copied into the executable Spring uber JAR, or you need to make sure that the Java attach API 在 Java 9+ 中激活。 這是我為 Java 8 所做的:

Maven:

<dependency>
  <groupId>com.sun</groupId>
  <artifactId>tools</artifactId>
  <version>1.8</version>
  <scope>system</scope>
  <systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
<!-- (...) -->
<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <mainClass>spring.aop.DemoApplication</mainClass>
    <!-- Important for tools.jar on Java 8 -->
    <includeSystemScope>true</includeSystemScope>
  </configuration>
</plugin>

<includeSystemScope>選項是必需的,因為否則 Boot 不知道如何找到附加的 API 類。 只需在 Gradle 中做一些等效的事情,就可以了。

Java:

您需要知道,為了附加代理,它必須是文件系統上的文件,而不僅僅是任何資源或輸入 stream。 這就是附加 API 的工作原理。 所以不幸的是,您必須先將其從 uber JAR 復制到文件系統。 這是您的操作方法:

public static boolean dynamicallyLoadAspectJAgent() {
  String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
  int p = nameOfRunningVM.indexOf('@');
  String pid = nameOfRunningVM.substring(0, p);
  try {
    VirtualMachine vm = VirtualMachine.attach(pid);
    ClassLoader classLoader = AgentLoader.class.getClassLoader();

    try (InputStream nestedJar = Objects.requireNonNull(classLoader.getResourceAsStream("BOOT-INF/lib/aspectjweaver-1.9.4.jar"))) {
      File targetFile = new File("aspectjweaver.jar");
      java.nio.file.Files.copy(nestedJar, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
      vm.loadAgent(targetFile.getAbsolutePath());
    }
    try (InputStream nestedJar = Objects.requireNonNull(classLoader.getResourceAsStream("BOOT-INF/lib/spring-instrument-5.1.9.RELEASE.jar"))) {
      File targetFile = new File("spring-instrument.jar");
      java.nio.file.Files.copy(nestedJar, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
      vm.loadAgent(targetFile.getAbsolutePath());
    }

    vm.detach();
  }
  catch (Exception e) {
    LOGGER.error("Exception while attaching agent", e);
    return false;
  }
  return true;
}

此外,就我而言,文件位於BOOT-INF/lib ,而不是WEB-INF/lib


更新:你說你在某個地方遇到了這個后續問題(重新格式化以提高可讀性):

failed to access class
  org.aspectj.weaver.loadtime.Aj$WeaverContainer
from class
  org.aspectj.weaver.loadtime.Aj
(
  org.aspectj.weaver.loadtime.Aj$WeaverContainer is in
    unnamed module of
    loader 'app';
  org.aspectj.weaver.loadtime.Aj is in
    unnamed module of
    loader org.springframework.boot.loader.LaunchedURLClassLoader @3e9b1010
)
at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:108)

這意味着Aj無法找到自己的內部 class Aj.WeaverContainer 這表明它們是在不同的時間點和不同的類加載器中加載的。 當從可執行 JAR 開始遠程調試到我的示例引導應用程序時,我看到應用程序類加載器實際上是LaunchedURLClassLoader的父級,即加載在父級中的 class 試圖訪問另一個 ZA2F2ED4F8EBC402CBB4C2 僅對其子類加載器可用在 Java 中是不可能的。 它只能反過來工作。

也許不從代理加載器內部導入和引用 AspectJ 編織器類會有所幫助。 嘗試注釋掉loadJavaAgent()isAspectJAgentLoaded()方法,並刪除import org.aspectj.weaver.loadtime.Agent; . 然后在您的應用程序中直接調用AgentLoader.dynamicallyLoadAspectJAgent()看看這是否有幫助。 關於代理加載,我還有一些優勢,但讓我們先讓它盡可能簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM