标签: jvm-bytecode

ByteBuddy:java.lang.IllegalArgumentException:无法附加未定义的变量:V

当从 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 bytecode byte-buddy jvm-bytecode

3
推荐指数
1
解决办法
996
查看次数

如何使用ByteBuddy创建动态代理

在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.

java proxy bytecode-manipulation byte-buddy jvm-bytecode

3
推荐指数
1
解决办法
2842
查看次数

Java字节码:局部变量表与堆栈计算

假设我们有以下课程:

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)

java jvm jvm-bytecode

3
推荐指数
2
解决办法
1219
查看次数

使用 ASM 的 JVM INVOKESPECIAL 私有构造函数

我正在使用 ASM 生成一些字节码并动态执行它。但在某些情况下,我需要调用私有构造函数,但我不知道如何调用。我知道可以通过反射(setAccessible)调用私有构造函数,但是我如何直接在字节码/jvm中执行此操作?

mv.visitMethodInsn(
        INVOKESPECIAL, target.byteCodeName(), "<init>", "()V", false
    )
Run Code Online (Sandbox Code Playgroud)

当 JVM 执行此代码时,它会抛出 java.lang.IllegalAccessError。

java jvm bytecode java-bytecode-asm jvm-bytecode

3
推荐指数
1
解决办法
953
查看次数

哪些 Java 代码生成 Wide 指令

我正在创建一个 JVM 并试图理解字节码指令。我正在尝试编写 Java 代码,该代码在编译时生成一个具有宽指令的 .class 文件。哪个 java 代码会生成那种扩展指令?我对广泛的行为有点迷失

java jvm bytecode instruction-set jvm-bytecode

3
推荐指数
1
解决办法
180
查看次数

对 lambda 函数的引用在哪里?

我试图准确地理解现代 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)

java lambda jvm jvm-bytecode

3
推荐指数
1
解决办法
78
查看次数

JVM中操作数栈的作用是什么?

JVM 运行时数据区为正在执行的每个方法单独的堆栈。它包含操作数堆栈和局部变量。每次加载变量时,都需要const先到操作数栈,然后store再到局部变量。为什么不直接操作局部变量表,还有一些看似重复的工作呢?

java jvm bytecode jvm-bytecode

3
推荐指数
1
解决办法
251
查看次数

JVM 如何在运行时知道行号?

编译 .java 文件时,它会生成一个包含字节码的 .class 文件。JVM 获取该字节码并执行它。这一步的字节,如果抛出异常,还会在源代码中提到这个错误发生在哪一行。但是字节码和源代码中的行号将完全不同,并且字节码在编译期间也不存储行号,因为我没有找到任何与之相关的助记符(并且存储行号只会增加代码大小)。那么有人可以告诉我 JVM 如何在抛出异常的源代码中获取确切的行号。

java line-numbers jvm-bytecode

3
推荐指数
1
解决办法
144
查看次数

在字节码层面,Java 的 Class.getEnumConstants() 如何知道哪些类是枚举类?

Java 反射 API 包含一个方法Class.getEnumConstants(),可以确定一个类是否是一个enum类(null如果它认为该类不是一个enum,则返回),以及它的常量是什么。

我正在开发一个直接生成 JVM 字节码的程序,并试图生成一个枚举类。因此,我需要知道 Java 如何从字节码中识别枚举类,这样getEnumConstants才能正常工作。显然,该类需要扩展Enum,但这显然是不够的(例如,对应于 的字节码public class Example extends Enum<Example> {}不会被识别为enum);类的 JVM 字节码还需要哪些其他功能,以便 Java 的反射 API 将其识别为 Java enum,并能够确定其枚举常量?

java reflection enums jvm-bytecode

2
推荐指数
1
解决办法
202
查看次数

为什么来自类的java字节码出现了新的静态内部类的代码出现jvm指令ACONST_NULL

我尝试新建一个内部静态类,但我发现字节码出现 jvm 指令ACONST_NULLbwteen NEWDUP并且INVOKE_SPECIAL,但我知道一个类 new 是

  • 新的
  • DUP
  • INVOKE_SPECIAL
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 jvm bytecode jvm-bytecode

2
推荐指数
1
解决办法
115
查看次数