我是罗纳德,JobRunr的作者.JobRunr是一个后台作业(job)调度库,它使用SerializedLambda和ASM来分析Java 8 lambda并将其转换为后台作业(job).

最近,报告了一个错误,我try 在JobRunr中重现它,以便编写一个测试来防止回归.

有趣的是,在相同的Java版本(17.0.2)上,即使我复制了完全相同的代码,我也无法重现它.

this project中,generated SerializedLambdaimplMethodKind等于5(REF_invokeVirtual).

然而,在JobRunr本身中,generated SerializedLambdaimplMethodKind等于7(REF_invokeSpecial).

生成SerializedLambda的实际代码如下:

public class GeoService {
    Logger LOG = LoggerFactory.getLogger(GeoService.class);

    public void executeGeoTreeJob(JobContext jobContext, long geoNameId, UserId userId) {
        LOG.error("Running: " + geoNameId);
    }

    public void run() {
        LOG.error("Starting job");
        UserId userId = new UserId();
        userId.setValue("test");
        long geoNameId = 1234;

        JobLambda jobLambda = () -> executeGeoTreeJob(JobContext.Null, geoNameId, userId);

        SerializedLambda serializedLambda = SerializedLambdaConverter.toSerializedLambda(jobLambda);
        System.out.println("=======");
        System.out.println("serializedLambda " + serializedLambda.getImplMethodKind());
        System.out.println("=======");

        BackgroundJob.enqueue(() -> executeGeoTreeJob(JobContext.Null, geoNameId, userId));
    }
}

this project中,generated SerializedLambdaimplMethodKind等于5(REF_invokeVirtual).

然而,在JobRunr本身中,generated SerializedLambdaimplMethodKind等于7(REF_invokeSpecial).

为什么implMethodKind的值不同?或者,换句话说,我需要对setup / JVM /.与示例项目中的结果相同.

Update:

我创建SerializedLambda如下:

public class SerializedLambdaConverter {

    private SerializedLambdaConverter() {

    }

    public static <T> SerializedLambda toSerializedLambda(T value) {
        if (!value.getClass().isSynthetic()) {
            throw new IllegalArgumentException("Please provide a lambda expression (e.g. BackgroundJob.enqueue(() -> myService.doWork()) instead of an actual implementation.");
        }

        if (!(value instanceof Serializable)) {
            throw new JobRunrException("The lambda you provided is not Serializable. Please make sure your functional interface is Serializable or use the JobLambda interface instead.");
        }

        try {
            Method writeReplaceMethod = value.getClass().getDeclaredMethod("writeReplace");
            makeAccessible(writeReplaceMethod);
            return (SerializedLambda) writeReplaceMethod.invoke(value);
        } catch (Exception shouldNotHappen) {
            throw shouldNotHappenException(shouldNotHappen);
        }
    }
}

低于javap的输出:

Compiled from "GeoService.java"
public class org.jobrunr.tests.e2e.services.GeoService {
  org.slf4j.Logger LOG;
  public org.jobrunr.tests.e2e.services.GeoService();
  public void executeGeoTreeJob(org.jobrunr.jobs.context.JobContext, long, org.jobrunr.tests.e2e.services.UserId);
  public void run();
}

附上在javap -verbose的输出中找到的标头(完整的输出对于so中的这里来说有点太多了):

Classfile /Users/rdehuyss/Projects/Personal/jobrunr/jobrunr/tests/e2e-vm-jdk/build/classes/java/main/org/jobrunr/tests/e2e/services/GeoService.class
  Last modified 20 Feb 2024; size 4064 bytes
  SHA-256 checksum 595969292bcac503d33a4e54c1b2a4ffa7517f8aa6c50a8a1470400981e08ecb
  Compiled from "GeoService.java"
public class org.jobrunr.tests.e2e.services.GeoService
  minor version: 0
  major version: 52

推荐答案

只是为了判断一下,你能不能试着修改一下你的.idea/compiler.xml,这部分:

   <bytecodeTargetLevel target="17">
      <module name="JobRunr.tests.e2e-elasticsearch-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-elasticsearch-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-json-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-mariadb-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-mariadb-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-mongo-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-mongo-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-mysql-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-mysql-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-oracle-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-oracle-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-postgres-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-postgres-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-redis-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-redis-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-sqlserver-gson.test" target="11" />
      <module name="JobRunr.tests.e2e-sqlserver-jackson.test" target="11" />
      <module name="JobRunr.tests.e2e-ui.main" target="11" />
      <module name="JobRunr.tests.e2e-ui.test" target="11" />
      <module name="JobRunr.tests.e2e-vm-jdk.test" target="11" /> <----- here
    </bytecodeTargetLevel>

Java相关问答推荐

我们如何直接使用kerminldap服务票证来通过ldap进行身份验证并形成LDAP上下文

具有默认分支的JUnit代码覆盖率切换声明

为什么我的画布没有显示在PFA应用程序中?

如何在Android上获取来电信息

如何在SystemiccationRetryListenerSupport中获得类级别的spring retryable annotation中指定的标签?

现场观看Android Studio中的变化

存根基类的受保护方法

在bash中将数组作为Java程序的参数传递

GSON期间的Java类型擦除

当Volatile关键字真的是必要的时候?

在Java 17中使用两个十进制数字分析时间时出错,但在Java 8中成功

使用htmlunit和java单击按钮

使用While循环打印素数,无法正常工作

如何在Jooq中获取临时表列引用?

JavaFX:为什么我的ComboBox添加了一个不必要的单元格的一部分?

升级版本后出现非法访问错误

获取401未经授权,即使在标头中设置了浏览器名称和cookie

MapStruct记录到记录的映射不起作用

为什么child-pom会创建一个新版本

什么是;u〃;平均值;jdku;在java开发工具包中?