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:
parent
341377bfed
commit
01368fe0d5
|
@ -4,6 +4,7 @@
|
||||||
package org.xerial.snappy;
|
package org.xerial.snappy;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.invoke.LambdaMetafactory;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
|
@ -37,21 +38,27 @@ final class SnappyFramed
|
||||||
Supplier<Checksum> supplier = null;
|
Supplier<Checksum> supplier = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
final Class crc32cClazz = Class.forName("java.util.zip.CRC32C");
|
final Class<?> crc32cClazz = Class.forName("java.util.zip.CRC32C");
|
||||||
final MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
// using LambdaMetafactory requires a caller sensitive lookup
|
||||||
|
final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||||
|
final MethodHandle conHandle = lookup.findConstructor(crc32cClazz, MethodType.methodType(void.class));
|
||||||
|
|
||||||
final MethodHandle conHandle = lookup.findConstructor(crc32cClazz, MethodType.methodType(void.class))
|
// use LambdaMetafactory to generate an implementation of Supplier<Checksum> which invokes
|
||||||
.asType(MethodType.methodType(Checksum.class));
|
// the java.util.zip.CRC32C default constructor
|
||||||
supplier = () -> {
|
supplier = (Supplier<Checksum>) LambdaMetafactory.metafactory(lookup,
|
||||||
try
|
// method name on Supplier
|
||||||
{
|
"get",
|
||||||
return (Checksum) conHandle.invokeExact();
|
// functional interface to be created by factory
|
||||||
}
|
MethodType.methodType(Supplier.class),
|
||||||
catch (Throwable e)
|
// type of the functional interface
|
||||||
{
|
// uses a generic, so erasure to Object
|
||||||
throw new IllegalStateException(e);
|
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)
|
catch(Throwable t)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue