在Maven Build中,我使用字节代码生成库(Byte Buddy)动态生成一些Java类型.当然,这些类文件没有相应的源文件.这种方式只能生成几个类.该项目的大部分代码都是Java源代码.理想情况下,Java源代码将以静态方式引用生成的类型,而不是使用反射或运行时代码生成,这意味着类需要位于javac的编译类路径上.我是否可以在同一个Maven项目的编译类路径上获取生成的类,即没有单独的Maven项目和工件来保存包含源代码的Maven项目引用的生成的字节代码?
更新:我已经尝试将生成的类直接放入target/classesie project.build.outputDirectory,在Maven Build Lifecycle的早期,但它似乎不在类路径上.Maven编译器插件或 IDE 无法解析生成的类型.我还尝试使用Build Helper Maven插件在target包含生成的类的情况下添加一个额外的资源目录,然后自动将其复制到该目录中target/classes.该配置表现出相同的问题.
更新:我在GitHub上创建了一个完整的公共回购:https://github.com/mches/so-42376851
这是项目的Maven POM,我希望有静态类引用字节码增强类:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>demo</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>demo-enhanced</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>demo</groupId>
<artifactId>demo-original</artifactId>
<version>${project.version}</version>
<overWrite>true</overWrite>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<includes>**/*.class</includes>
<excludes>META-INF/</excludes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>transform</goal>
</goals>
<configuration> …Run Code Online (Sandbox Code Playgroud) 我启用了内联模拟,以便我可以模拟最终类,但现在我在使用Junit运行测试时遇到以下异常.
当我立即运行所有测试时,只有两个测试失败,但如果我单独运行测试,那么大多数测试都会失败.
我没有使用任何scala或android类(我知道).我正在使用lombok,但我尝试删除lombok注释任何它没有解决问题.
当删除mock-maker-inline时问题消失了,但我宁愿保留它.
我该如何解决这个问题?
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class com.example.MyClass.
If you're not sure why you're getting this error, please report to the mailing list.
Java : 1.8
JVM vendor name : Oracle Corporation
JVM vendor version : 25.112-b15
JVM name : Java HotSpot(TM) 64-Bit Server VM
JVM version : 1.8.0_112-b15
JVM info : mixed mode
OS name : Windows 10
OS version : 10.0
You are seeing this disclaimer because Mockito is configured to …Run Code Online (Sandbox Code Playgroud) 我正在使用 Powermockito 来模拟和监视静态类。版本:2.0.4
还使用mockito-core版本3.0.0。在我的一个项目中,我能够通过启用这里指定的 mock-maker-inline 来模拟静态 https://github.com/powermock/powermock-examples-maven/blob/master/mockito2/src/test/resources/ org/powermock/extensions/configuration.properties
但是,当我在另一个项目上尝试相同的方法时,遇到以下错误:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.ghx.tpm.api.ISubscribedProductParameterService]: Factory method 'subscribedProductParameterService' threw exception; nested exception is java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
Caused by: java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
Caused by: java.lang.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in sun.misc.CompoundEnumeration@614aeccc
Caused by: java.lang.IllegalStateException: Failed to load MockMaker implementation: mock-maker-inline
Caused by: java.lang.IllegalStateException: Internal problem occurred, please report it. Mockito …Run Code Online (Sandbox Code Playgroud) 问题是创建现有对象的动态增强版本.
我不能修改对象的Class.相反,我必须:
Class添加到现有对象的接口是:
public interface EnhancedNode {
Node getNode();
void setNode(Node node);
Set getRules();
void setRules(Set rules);
Map getGroups();
void setGroups(Map groups);
}
Run Code Online (Sandbox Code Playgroud)
有了Byte Buddy,我设法子类化并实现了我的界面.问题是委托给包装对象.我发现这样做的唯一方法是使用反射太慢(我对应用程序负载很重,性能很关键).
到目前为止我的代码是:
Class<? extends Node> proxyType = new ByteBuddy()
.subclass(node.getClass(), ConstructorStrategy.Default.IMITATE_SUPER_TYPE_PUBLIC)
.method(anyOf(finalNode.getClass().getMethods())).intercept(MethodDelegation.to(NodeInterceptor.class))
.defineField("node", Node.class, Visibility.PRIVATE)
.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
.defineField("groups", Map.class, Visibility.PRIVATE)
.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
.defineField("rules", Set.class, Visibility.PRIVATE)
.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
enhancedClass = (Class<N>) proxyType;
EnhancedNode enhancedNode = (EnhancedNode) enhancedClass.newInstance();
enhancedNode.setNode(node);
Run Code Online (Sandbox Code Playgroud)
Node子类/包装的对象在哪里.在NodeInterceptor被调用的方法前锋getNode财产.
这里的代码NodeInterceptor: …
我想在运行时为使用Byte Buddy的抽象类创建一个实现,我面临的问题java.lang.AbstractMethodError是,从创建的实例调用方法时会抛出a.我有一个abstract像这样的现有类(我实际上无法修改,实际上包含更多逻辑):
public abstract class Algorithm {
abstract int execute();
}
Run Code Online (Sandbox Code Playgroud)
使用以下最小样本,我希望我的Algorithm实例返回一个常量值:
Class<?> type = new ByteBuddy()
.subclass(Algorithm.class)
.method(ElementMatchers.named("execute"))
.intercept(FixedValue.value(42))
.make()
.load(classLoader, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Algorithm instance = (Algorithm) type.newInstance();
System.out.println(myInstance.execute());
Run Code Online (Sandbox Code Playgroud)
然而,这会导致以下异常:
Exception in thread "main" java.lang.AbstractMethodError: package.Algorithm.execute()I
Run Code Online (Sandbox Code Playgroud)
(当我实验性地Algorithm改为a时interface,一切正常,但这并不能解决我的具体问题).
我正在尝试生成具有循环类依赖性的类,类似于这个问题:Byte Buddy - 处理生成的类中的循环引用
作为一个最小的例子,我想要生成的类有这样的依赖:
//class A depends on class B, and vice-versa
final class A { B theB; }
final class B { A theA; }
Run Code Online (Sandbox Code Playgroud)
上面链接中接受的答案没有为我提供足够的信息来实现这一点.这是我试过的:
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.jar.asm.Opcodes;
public class ByteBuddyHello {
public static void main(String[] args) {
try {
final ByteBuddy bb = new ByteBuddy();
final TypeDescription.Latent typeDescrA = new TypeDescription.Latent("A", 0, null, null);
final TypeDescription.Latent typeDescrB = new TypeDescription.Latent("B", 0, null, null);
final DynamicType.Unloaded<Object> madeA = bb …Run Code Online (Sandbox Code Playgroud) 我正在使用ByteBuddy在运行时使用动态生成的字节代码创建一个类.生成的类执行它要执行的操作,但我想手动检查生成的字节代码,以确保它是正确的.
例如
Class<?> dynamicType = new ByteBuddy()
.subclass(MyAbstractClass.class)
.method(named("mymethod"))
.intercept(new MyImplementation(args))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Run Code Online (Sandbox Code Playgroud)
其中MyImplementation将多个StackManipulation命令链接在一起以创建动态生成的代码.
我可以将生成的类编写到文件中(因此我可以使用IDE手动检查),或者打印出生成的类的字节码吗?
我正在使用Mockito 2和Espresso进行单元测试,并且在尝试在Instrumentation测试中使用Mockito 2时遇到了问题。运行测试时,出现此错误
java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:74)
at java.lang.reflect.Proxy.invoke(Proxy.java:913)
at $Proxy5.isTypeMockable(Unknown Source)
at org.mockito.internal.util.MockUtil.typeMockabilityOf(MockUtil.java:29)
at org.mockito.internal.util.MockCreationValidator.validateType(MockCreationValidator.java:22)
at org.mockito.internal.creation.MockSettingsImpl.validatedSettings(MockSettingsImpl.java:232)
at org.mockito.internal.creation.MockSettingsImpl.build(MockSettingsImpl.java:226)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:64)
at org.mockito.Mockito.mock(Mockito.java:1864)
at org.mockito.Mockito.mock(Mockito.java:1777)
at com.armop.insight.views.activity.InsightActivityTest.testUserResultReturnsEmpty(InsightActivityTest.kt:66)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at android.support.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) …Run Code Online (Sandbox Code Playgroud) 我在我的项目中使用 Mockito 2.23.4 和 byte-buddy 1.9.3。我想模拟最终类和方法,所以我在这篇文章Mockito 模拟最终类和方法以及项目目录中的mock-maker-inline内部文件设置之后使用了mockito-inline 。我还跟进了Mockito 因无效参数名称异常而启用内联模拟而失败的帖子,但问题仍然存在。但是当我运行测试时,我得到下面的堆栈跟踪。org.mockito.plugins.MockMakersrc/test/resources/mockito-extensions
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
Test ignored.
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class org.elasticsearch.client.RestHighLevelClient.
If you're not sure why you're getting this error, please report to the mailing list.
Java : 15
JVM vendor name : Oracle Corporation
JVM vendor version : 15.0.2+7-27
JVM name : Java …Run Code Online (Sandbox Code Playgroud) 我正在尝试将Cglib代理转换为ByteBuddy.Cglib有net.sf.cglib.proxy.Proxy接口来拦截所有方法调用.我检查了ByteBuddy的文档但是找不到这样的例子.如果我没有用ByteBuddy实例化的每个对象都有这样的接口,我会再次重复同样的事情并且agin.使用ByteBuddy有更好的方法吗?
这是我的示例代码段:
服务:
public class MyService {
public void sayFoo() {
System.out.println("foo");
}
public void sayBar() {
System.out.println("bar");
}
}
Run Code Online (Sandbox Code Playgroud)
拦截器:
public class MyServiceInterceptor {
public void sayFoo(@SuperCall Callable<Void> zuper) {
try {
zuper.call();
} catch (Exception e) {
e.printStackTrace();
}
}
public void sayBar(@SuperCall Callable<Void> zuper) {
try {
zuper.call();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
测试:
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.dynamic.ClassLoadingStrategy;
import net.bytebuddy.instrumentation.MethodDelegation;
import net.bytebuddy.instrumentation.method.matcher.MethodMatchers;
public class Main {
public static void …Run Code Online (Sandbox Code Playgroud) byte-buddy ×10
java ×8
bytecode ×5
mockito ×3
junit ×2
android ×1
class ×1
decorator ×1
interface ×1
kotlin ×1
maven ×1
powermockito ×1
reflection ×1
unit-testing ×1