From 01368fe0d59dba8641b4ee89b497d4ee1d3544f2 Mon Sep 17 00:00:00 2001 From: Brett Okken Date: Tue, 10 Sep 2024 14:22:02 -0500 Subject: [PATCH] internal: use LambdaMetafactory to generate java.util.zip.CRC32C instances (#595) currently we have written a lambda (turns into anonymous class) which invokes a MethodHandle for the java.util.zip.CRC32C constructor as the Supplier implementation. This has 2 layers of misdirection. The Supplier implementation spun up by the jvm calls the anonymous lambda class, which then calls the MethodHandle invoke. This leads to stack traces like: use LambdaMetafactory to generate a Supplier which calls the java.util.zip.CRC32C Co-authored-by: bo8979 --- .../java/org/xerial/snappy/SnappyFramed.java | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/xerial/snappy/SnappyFramed.java b/src/main/java/org/xerial/snappy/SnappyFramed.java index a1de1479..0c28eac2 100644 --- a/src/main/java/org/xerial/snappy/SnappyFramed.java +++ b/src/main/java/org/xerial/snappy/SnappyFramed.java @@ -4,6 +4,7 @@ package org.xerial.snappy; import java.io.IOException; +import java.lang.invoke.LambdaMetafactory; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -37,21 +38,27 @@ final class SnappyFramed Supplier supplier = null; try { - final Class crc32cClazz = Class.forName("java.util.zip.CRC32C"); - final MethodHandles.Lookup lookup = MethodHandles.publicLookup(); - - final MethodHandle conHandle = lookup.findConstructor(crc32cClazz, MethodType.methodType(void.class)) - .asType(MethodType.methodType(Checksum.class)); - supplier = () -> { - try - { - return (Checksum) conHandle.invokeExact(); - } - catch (Throwable e) - { - throw new IllegalStateException(e); - } - }; + final Class crc32cClazz = Class.forName("java.util.zip.CRC32C"); + // using LambdaMetafactory requires a caller sensitive lookup + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + final MethodHandle conHandle = lookup.findConstructor(crc32cClazz, MethodType.methodType(void.class)); + + // use LambdaMetafactory to generate an implementation of Supplier which invokes + // the java.util.zip.CRC32C default constructor + supplier = (Supplier) LambdaMetafactory.metafactory(lookup, + // method name on Supplier + "get", + // functional interface to be created by factory + MethodType.methodType(Supplier.class), + // type of the functional interface + // uses a generic, so erasure to Object + MethodType.methodType(Object.class), + // the method handle to call + conHandle, + // type as used at call site + MethodType.methodType(Checksum.class)) + .getTarget() + .invoke(); } catch(Throwable t) {