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<Checksum> 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<Checksum> which calls the
java.util.zip.CRC32C

Co-authored-by: bo8979 <bo8979@cerner.com>
This commit is contained in:
Brett Okken 2024-09-10 14:22:02 -05:00 committed by GitHub
parent 341377bfed
commit 01368fe0d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 22 additions and 15 deletions

View File

@ -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<Checksum> 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<Checksum> which invokes
// the java.util.zip.CRC32C default constructor
supplier = (Supplier<Checksum>) 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)
{