[英]How to get access to WEB-INF/lib/ jars?
我有 Gradle 項目與Spring Boot和AspectJ 。
想要直接從 WEB-INF/libs 動態加載aspectjweaver
和spring-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;
}
}
但是發現null
中getResource()
的返回值
處理此問題的最佳解決方案是什么?
尼基塔,今天是你的幸運日。 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.