当从 Google Guava 重新构建该类时com.google.common.collect.ImmutableMultimap$Values,我从 ByteBuddy 收到 IllegalArgumentException。
内部类是com.google.common.collect.ImmutableCollection其方法ImmutableList<E> createAsList()导致问题的子类。
堆栈跟踪:
Exception in thread "main" java.lang.IllegalArgumentException: Cannot attach undefined variable: V
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForAttachment.onTypeVariable(TypeDescription.java:1973)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForAttachment.onTypeVariable(TypeDescription.java:1896)
at net.bytebuddy.description.type.TypeDescription$Generic$OfTypeVariable$Symbolic.accept(TypeDescription.java:5551)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor.onParameterizedType(TypeDescription.java:1857)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForAttachment.onParameterizedType(TypeDescription.java:1896)
at net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType.accept(TypeDescription.java:5017)
at net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod.getReturnType(Transformer.java:377)
at net.bytebuddy.description.method.MethodDescription$AbstractBase.asTypeToken(MethodDescription.java:685)
at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Prepared$Entry.resolveBridgeTypes(MethodRegistry.java:916)
at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Prepared.compile(MethodRegistry.java:778)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$RedefinitionClassVisitor.visit(TypeWriter.java:3281)
at net.bytebuddy.jar.asm.ClassReader.accept(Unknown Source)
at net.bytebuddy.jar.asm.ClassReader.accept(Unknown Source)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:3018)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1617)
at net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder.make(RebaseDynamicTypeBuilder.java:198)
at net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder.make(AbstractInliningDynamicTypeBuilder.java:90)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2566)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2668)
at cl.InnerClassLoader.loadClass(InnerClassLoader.java:187)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at test.Stuff.<init>(Stuff.java:15)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at …Run Code Online (Sandbox Code Playgroud) 在Java中,可以使用实现来创建动态代理InvocationHandler.尽管进行了JVM优化,但使用反射总是会有一些调用方法的开销.
为了尝试解决这个问题,我尝试使用ByteBuddy在运行时创建代理类,但文档在这方面似乎不够清晰.
如何创建一个MethodCallProxy方法以将方法调用转发到某个类实例?
编辑:
为了更好地澄清我的问题,我提供了一个我想要实现的例子:
我正在构建一个RPC系统.在方法调用的每一侧,我都有一个定义契约的接口(当调用者/被调用者都在JVM下运行时).
@Contract
interface ISomeService {
fun someMethod(arg0: String, arg1: SomePojo): PojoResult
}
Run Code Online (Sandbox Code Playgroud)
在调用站点,我注入一个代理,拦截所有方法调用并将它们转发给被调用者.
ByteBuddy()
.subclass(Any::class.java)
.implement(serviceClass)
// Service contract method delegation
.method(isDeclaredBy(serviceClass)).intercept(
MethodDelegation
.to(ServiceProxyInterceptor())
.filter(not(isDeclaredBy(Any::class.java)))
)
.make()
.load(this)
.loaded as Class<T>
Run Code Online (Sandbox Code Playgroud)
最后,在被调用者,我有几个处理程序,每个服务方法一个,负责解组调用参数并将它们转发到服务实现.
@Service
class SomeServiceImpl {
fun someMethod(arg0: String, arg1: SomePojo): PojoResult {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我可以使用代码生成来解决这个问题,但生成的jar文件会变得非常大.因此,我想创建这些处理程序的通用版本,并在每个实例中附加一个代理,该代理拦截每个方法调用ISomeService并转发它们SomeServiceImpl.
假设我们有以下课程:
final class Impl implements Gateway3 {
private final Sensor sensor1;
private final Sensor sensor2;
private final Sensor sensor3;
private final Alarm alarm;
public Impl(Sensor sensor1, Sensor sensor2, Sensor sensor3, Alarm alarm) {
this.sensor1 = sensor1;
this.sensor2 = sensor2;
this.sensor3 = sensor3;
this.alarm = alarm;
}
@Override
public Temperature averageTemp() {
final Temperature temp1 = sensor1.temperature();
final Temperature temp2 = sensor2.temperature();
final Temperature temp3 = sensor3.temperature();
final Average tempAvg = new Average.Impl(temp1, temp2, temp3);
final Temperature result = tempAvg.result();
return …Run Code Online (Sandbox Code Playgroud) 我正在使用 ASM 生成一些字节码并动态执行它。但在某些情况下,我需要调用私有构造函数,但我不知道如何调用。我知道可以通过反射(setAccessible)调用私有构造函数,但是我如何直接在字节码/jvm中执行此操作?
mv.visitMethodInsn(
INVOKESPECIAL, target.byteCodeName(), "<init>", "()V", false
)
Run Code Online (Sandbox Code Playgroud)
当 JVM 执行此代码时,它会抛出 java.lang.IllegalAccessError。
我正在创建一个 JVM 并试图理解字节码指令。我正在尝试编写 Java 代码,该代码在编译时生成一个具有宽指令的 .class 文件。哪个 java 代码会生成那种扩展指令?我对广泛的行为有点迷失
我试图准确地理解现代 Java 中 lambdas 和高阶函数在 JVM 级别是如何工作的。我写了这个简单的测试类:
public final class Main {
public static void main(String[] args) {
var s = new Object[] { 1.0, 2.0, 3.0 };
System.out.println(sum(s, x -> 1000000.0));
}
public static double sum(Object[] s, Function<Object, Double> f) {
var r = 0.0;
for (var a : s) {
r += f.apply(a);
}
return r;
}
}
Run Code Online (Sandbox Code Playgroud)
编译成这样:
Compiled from "Main.java"
public final class prover.Main {
public prover.Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V …Run Code Online (Sandbox Code Playgroud) JVM 运行时数据区为正在执行的每个方法单独的堆栈。它包含操作数堆栈和局部变量。每次加载变量时,都需要const先到操作数栈,然后store再到局部变量。为什么不直接操作局部变量表,还有一些看似重复的工作呢?
编译 .java 文件时,它会生成一个包含字节码的 .class 文件。JVM 获取该字节码并执行它。这一步的字节,如果抛出异常,还会在源代码中提到这个错误发生在哪一行。但是字节码和源代码中的行号将完全不同,并且字节码在编译期间也不存储行号,因为我没有找到任何与之相关的助记符(并且存储行号只会增加代码大小)。那么有人可以告诉我 JVM 如何在抛出异常的源代码中获取确切的行号。
Java 反射 API 包含一个方法Class.getEnumConstants(),可以确定一个类是否是一个enum类(null如果它认为该类不是一个enum,则返回),以及它的常量是什么。
我正在开发一个直接生成 JVM 字节码的程序,并试图生成一个枚举类。因此,我需要知道 Java 如何从字节码中识别枚举类,这样getEnumConstants才能正常工作。显然,该类需要扩展Enum,但这显然是不够的(例如,对应于 的字节码public class Example extends Enum<Example> {}不会被识别为enum);类的 JVM 字节码还需要哪些其他功能,以便 Java 的反射 API 将其识别为 Java enum,并能够确定其枚举常量?
我尝试新建一个内部静态类,但我发现字节码出现 jvm 指令ACONST_NULLbwteen NEW,DUP并且INVOKE_SPECIAL,但我知道一个类 new 是
package com.hoho.api;
/**
* @author linuxea
*/
public class Main {
private static class InnerMain {
// no field
}
public static void main(String[] args) {
InnerMain innerMain = new InnerMain();
}
}
Run Code Online (Sandbox Code Playgroud)
// class version 52.0 (52)
// access flags 0x21
public class com/hoho/api/Main {
// compiled from: Main.java
// access flags 0xA
private static INNERCLASS com/hoho/api/Main$InnerMain com/hoho/api/Main InnerMain
// access flags 0x1008 …Run Code Online (Sandbox Code Playgroud) java ×10
jvm-bytecode ×10
jvm ×6
bytecode ×5
byte-buddy ×2
enums ×1
lambda ×1
line-numbers ×1
proxy ×1
reflection ×1