我是罗纳德,JobRunr的作者.JobRunr是一个后台作业(job)调度库,它使用SerializedLambda和ASM来分析Java 8 lambda并将其转换为后台作业(job).
最近,报告了一个错误,我try 在JobRunr中重现它,以便编写一个测试来防止回归.
有趣的是,在相同的Java版本(17.0.2)上,即使我复制了完全相同的代码,我也无法重现它.
在this project中,generated SerializedLambda
的implMethodKind
等于5(REF_invokeVirtual
).
然而,在JobRunr本身中,generated SerializedLambda
的implMethodKind
等于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 SerializedLambda
的implMethodKind
等于5(REF_invokeVirtual
).
然而,在JobRunr本身中,generated SerializedLambda
的implMethodKind
等于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