希望对某人来说这是一个简单的问题.....
我正在使用RAD 7.5.2,正在编写Junit测试.我用JUnit 3编写它们就好了,然后我想模拟一些函数调用.所以我加载了jmockit 0.9.7和Junit 4.6.我还包括-javaagent:jmockit.jar作为VM参数.
当我"运行为Junit测试"时,它完全没有任何问题(至少,我没有看到输出).Junit的输出很好,没有错误被转储到控制台.
当我"调试为Junit测试"时,它将无法正常工作.它让我陷入:
InstrumentationImpl.class - >未找到源
......当我继续......
NativeMethodAccessorImpl.class - >找不到源
......当我继续打...
JUnit在此之后结束.它将以下内容转储到控制台:
异常线程 "main" java.lang.reflect.InvocationTargetException在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl .java:43)在sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:160)的java.lang.reflect.Method.invoke(Method.java:618)中引起:java.lang.UnsatisfiedLinkError:sun/instrument/InstrumentationImpl.redefineClasses0([Ljava/lang/instrument/ClassDefinition;)V at the sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:98)at mockit.internal.RedefinitionEngine.redefineMethods(RedefinitionEngine.java:197)at mockit.internal.在mockit.internal.RedefinitionEngine.setUpInternalStartupMock(RedefinitionEngine.j)上的mockit.internal.RedefinitionEngine.redefineMethods(RedefinitionEngine.java:116)重新定义引擎.重定义方法(RedefinitionEngine.java:184)ava:53)at mockit.internal.Startup.loadInternalStartupMocks(Startup.java:123)at mockit.internal.Startup.initialize(Startup.java:110)at mockit.internal.Startup.premain(Startup.java:97). ..还有5个
致命错误:-javaagent的处理失败
我可以在我的测试中同时运行JUnit 3和JUnit 4,没问题,当我使用-javaagent:jmockit.jar(使用调试器;他们自己很好)时,事情变得丑陋,我必须这样做使用jmockit的东西.
思考?
我ClassFileTransformer使用ASM为javaagent 实现了一个.因为它有一些bug,我想为它编写一个JUnit测试用例.我该怎么做呢?
使用伪代码我想的是:
// Have a test class as subject
public static class Subject {
public void doSomething(){...}
}
// Manually load and transform the subject
...?
// Normally execute some now transformed methods of the subject
new Subject().doSomething();
// Check the result of the call (i.e. whether the correct attached methods were called)
Assert.assertTrue(MyClassFileTransformer.wasCalled());
Run Code Online (Sandbox Code Playgroud)
现在的问题是:如何手动加载和转换主题并使JVM/Classloader使用我的操作版本?或者我完全错过了什么?
我正在学习javaagent,我创建了一个简单的探查器
http://www.javabeat.net/2012/06/introduction-to-java-agents/
我描述了一个java应用程序,它工作正常.我可以使用此分析器来分析在tomcat中部署的Web应用程序.我在CATALINA.bat"SET JAVA_OPTS =%JAVA_OPTS%-javaagent:/path-to-profiler/profiler.jar"中尝试了此设置并启动了服务器但我没有找到所需的输出.
我创建了一个 javaagent jar 文件并将其附加到一个 web 应用程序(通过-javaagent在 web 应用程序启动时使用关键字)。我怎样才能用 eclipse 远程调试这个 javaagent
我试图使用instrumentation调试java应用程序.当前系统的问题是
这使得很难追溯功能损坏的根本原因.
为了处理这种情况,我开发了工具,使用InstrumentationAPI的java代理,我能够注入日志语句,并解决了一半的问题.
但下一个问题是记录异常.我想扩展我的工具记录在应用程序执行期间抛出的每个异常.我尝试使用注入"的try-catch"块javaassist为方法API(使用addCatch,insertBefore和insertAfter),并且它是有效的一定程度.
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
throws IllegalClassFormatException {
if (className.startsWith("com/alu/")) {
return insertLog(className, classBeingRedefined, classfileBuffer);
}
if(className.endsWith("Exception")){
System.out.println("============= exception occured "+className);
}
Run Code Online (Sandbox Code Playgroud)
这里 inserLog(..)方法将注入必要的日志语句并且工作正常,但是当有任何异常时它不会转换为变换器.
但问题是一些方法处理异常内部(即使没有log/sysout).
例如:
try {
if(search.equals("Category")){
//do operation
}
} catch (Exception e) {
}
Run Code Online (Sandbox Code Playgroud)
这个代码NullPointerException在值为searchnull 时吃,我从来不知道这个异常和应用程序失败了.
最终我想要的是记录应用程序抛出的任何异常的机制.以下详细信息将被捕获
我知道有API Thread.setDefaultUncaughtExceptionHandler,但不确定它如何与java检测一起使用.我没有任何源访问该应用程序.
[更新1]
我发现下面链接告诉使用retransformation,我会试一试并更新 …
这是我的运行配置.
task run << {
jvmArgs "-javaagent:/home/audrius/org.springframework.instrument-3.0.5.RELEASE.jar"
jettyRun.execute()
}
Run Code Online (Sandbox Code Playgroud)
但它给了我:
Could not find method jvmArgs()
Run Code Online (Sandbox Code Playgroud)
你如何为jettyRun设置javaagent?
我正在使用jetty-alpn-agent来向项目添加ALPN支持,但我能找到的是关于如何从.m2文件夹运行它的说明,这使我需要部署两个jar:s而不是仅部署一个uber-jar,从而减少了便携式的。
是否可以在jar中指定-javaagent开关的位置?
我正在寻找类似的东西java -javaagent:my.jar!/javaagents/jetty-alpn-agent-2.0.0.jar -jar myjar.jar,但这似乎不起作用。
我正在为一个大型项目编写单元测试,我需要将 JVM 参数传递给它,这些是我的 JVM 参数内置到该项目的 Eclipse 运行配置中:
--module-path lib/javafx-sdk-13.0.2/lib --add-modules=javafx.controls
-javaagent:lib/aspectjweaver-1.9.5.jar
-javaagent:lib/spring-instrument-5.2.3.RELEASE.jar
Run Code Online (Sandbox Code Playgroud)
我的问题是我需要为每个 JUnit 测试或测试序列添加这些参数。有没有更好的方法呢?无需手动将这些参数添加到我创建的每个新测试中的某种方法?
******编辑******
这也有一个令人讨厌的副作用,即根本不让我构建这个项目!Maven 不使用我的自定义 JUnit 运行配置来运行应用程序的整个测试集(这很好用,因为我在那里设置了 JVM 参数),而是使用它自己的,因为参数不存在,这显然失败了。这是一个大问题,有没有办法以某种方式将这些 JVM 参数直接“硬编码”到 POM 中?
****** 编辑 2 ******
这是我的 POM.xml 文件中的 Spring-Boot-Maven-Plugin 配置:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmArguments>
--module-path lib/javafx-sdk-13.0.2/lib
--add-modules=javafx.controls
-javaagent:lib/aspectjweaver-1.9.5.jar
-javaagent:lib/spring-instrument-5.2.3.RELEASE.jar
</jvmArguments>
</configuration>
</plugin>
Run Code Online (Sandbox Code Playgroud)
******解决方案******
添加 Maven Surefire 插件并以这种方式设置它解决了这个问题:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<configuration>
<argLine>
--module-path lib/javafx-sdk-13.0.2/lib
--add-modules=javafx.controls
-javaagent:lib/aspectjweaver-1.9.5.jar
-javaagent:lib/spring-instrument-5.2.3.RELEASE.jar
</argLine>
</configuration>
</plugin> …Run Code Online (Sandbox Code Playgroud) 我制作了一个 Java 代理,它在运行时连接到 JVM并检测所有加载的项目类并插入一些日志记录语句。总共有11k个班级。余测量由所花费的总时间transform我的方法ClassFileTransformer,它是3秒。但整个仪器过程的持续时间大约需要 30 秒。这就是我重新转换课程的方式:
instrumentation.retransformClasses(myClassesArray);
Run Code Online (Sandbox Code Playgroud)
我假设 JVM 占用了大部分时间来重新加载更改的类。那正确吗?如何加快检测过程?
更新:
当我的代理被附加时,
instrumentation.retransformClasses(myClassesArray);
Run Code Online (Sandbox Code Playgroud)
只调用一次。
然后MyTransfomerclass 检测类并测量检测的总持续时间:
instrumentation.addTransformer(new MyTransfomer(), true);
instrumentation.retransformClasses(retransformClassArray);
Run Code Online (Sandbox Code Playgroud)
在所有类都被检测(从初始数组)(全局缓存跟踪检测的类)之后total,打印出来,大约需要 3 秒。但max-min大约是 30 秒。
更新 2:
查看堆栈跟踪后,发生了以下情况:我调用
instrumentation.retransformClasses(retransformClassArray);
Run Code Online (Sandbox Code Playgroud)
它调用本机方法retransformClasses0()。一段时间后(!)JVM 调用该类的transform()方法sun.instrument.InstrumentationImpl(但该方法一次只使用一个类,因此 JVM 连续多次调用该方法),它调用具有包含所有类的列表transform()的sun.instrument.TransformerManager对象ClassTransformers注册并调用这些转换器中的每一个来转换类(我只注册了一个转换器!!)。
所以在我看来,大部分时间都花在 JVM 上(在retransformClasses0()被调用之后和每次调用之前sun.instrument.InstrumentationImpl.transform())。有没有办法减少 JVM 执行此任务所需的时间?
对于需要 javaagent(例如 OpenTelemetry)的系统,文档通常以“从此 URL 下载代理 JAR 并将其添加到命令行”开头。在使用 Maven Central 很好地处理库依赖关系并具有稳定版本控制等的世界中,相比之下,“下载 JAR”方法似乎原始且不安全。
在使用 Gradle 构建的项目中获取 javaagent 库的最佳实践是什么?“下载这个 jar”真的是当前最先进的技术吗?
我现在对 OpenTelemetry 特别感兴趣。如果有一个只适用于 OpenTelemetry 的答案(例如 Gradle 插件),我会洗耳恭听。