Skip to content

Commit

Permalink
internal: use LambdaMetafactory to generate java.util.zip.CRC32C inst…
Browse files Browse the repository at this point in the history
…ances (#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>
  • Loading branch information
bokken and bo8979 authored Sep 10, 2024
1 parent 341377b commit 01368fe
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions src/main/java/org/xerial/snappy/SnappyFramed.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down

0 comments on commit 01368fe

Please sign in to comment.