Home / Class/ CleanerJava24Linker Class — netty Architecture

CleanerJava24Linker Class — netty Architecture

Architecture documentation for the CleanerJava24Linker class in CleanerJava24Linker.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  0c08734e_1658_4777_76f5_6b6460f4d613["CleanerJava24Linker"]
  04dd755a_bbac_35e6_9950_f61de6d82a81["CleanerJava24Linker.java"]
  0c08734e_1658_4777_76f5_6b6460f4d613 -->|defined in| 04dd755a_bbac_35e6_9950_f61de6d82a81
  b94ea4fa_d4e1_cf89_a47c_d51ac16c6661["isSupported()"]
  0c08734e_1658_4777_76f5_6b6460f4d613 -->|method| b94ea4fa_d4e1_cf89_a47c_d51ac16c6661
  65531363_523d_b5dd_924f_8397afa410b0["CleanableDirectBuffer()"]
  0c08734e_1658_4777_76f5_6b6460f4d613 -->|method| 65531363_523d_b5dd_924f_8397afa410b0
  ebd05de7_0269_7e2c_73c6_39149ca749b6["freeDirectBuffer()"]
  0c08734e_1658_4777_76f5_6b6460f4d613 -->|method| ebd05de7_0269_7e2c_73c6_39149ca749b6
  add871eb_c3ef_e875_fa27_a4789f284655["malloc()"]
  0c08734e_1658_4777_76f5_6b6460f4d613 -->|method| add871eb_c3ef_e875_fa27_a4789f284655
  3017c0a9_56e5_6be2_057b_82f345655d57["free()"]
  0c08734e_1658_4777_76f5_6b6460f4d613 -->|method| 3017c0a9_56e5_6be2_057b_82f345655d57

Relationship Graph

Source Code

common/src/main/java/io/netty/util/internal/CleanerJava24Linker.java lines 28–269

public class CleanerJava24Linker implements Cleaner {
    private static final InternalLogger logger;

    private static final MethodHandle INVOKE_MALLOC;
    private static final MethodHandle INVOKE_CREATE_BYTEBUFFER;
    private static final MethodHandle INVOKE_FREE;

    static {
        boolean suitableJavaVersion;
        if (System.getProperty("org.graalvm.nativeimage.imagecode") != null) {
            // native image supports this since 25, but we don't use PlatformDependent0 here, since
            // we need to initialize CleanerJava24Linker at build time.
            String v = System.getProperty("java.specification.version");
            try {
                suitableJavaVersion = Integer.parseInt(v) >= 25;
            } catch (NumberFormatException e) {
                suitableJavaVersion = false;
            }
            // also need to prevent initializing the logger at build time
            logger = null;
        } else {
            // Only attempt to use MemorySegments on Java 24 or greater, where warnings about Unsafe
            // memory access operations start to appear.
            // The following JDK bugs do NOT affect our implementation because the memory segments we
            // create are associated with the GLOBAL_SESSION:
            // - https://bugs.openjdk.org/browse/JDK-8357145
            // - https://bugs.openjdk.org/browse/JDK-8357268
            suitableJavaVersion = PlatformDependent0.javaVersion() >= 24;
            logger = InternalLoggerFactory.getInstance(CleanerJava24Linker.class);
        }

        MethodHandle mallocMethod;
        MethodHandle wrapMethod;
        MethodHandle freeMethod;
        Throwable error;

        if (suitableJavaVersion) {
            try {
                // First, we need to check if we have access to "restricted" methods through the Java Module system.
                MethodHandles.Lookup lookup = MethodHandles.lookup();
                Class<?> moduleCls = Class.forName("java.lang.Module");
                MethodHandle getModule = lookup.findVirtual(
                        Class.class, "getModule", methodType(moduleCls));
                MethodHandle isNativeAccessEnabledModule = lookup.findVirtual(
                        moduleCls, "isNativeAccessEnabled", methodType(boolean.class));
                MethodHandle isNativeAccessEnabledForClass = MethodHandles.filterArguments(
                        isNativeAccessEnabledModule, 0, getModule);
                boolean isNativeAccessEnabled =
                        (boolean) isNativeAccessEnabledForClass.invokeExact(CleanerJava24Linker.class);
                if (!isNativeAccessEnabled) {
                    throw new UnsupportedOperationException(
                            "Native access (restricted methods) is not enabled for the io.netty.common module.");
                }

                // Second, we need to check the size of a pointer address. For simplicity, we'd like to assume the size
                // of an address is the same as a Java long. So effectively, we're only enabled on 64-bit platforms.
                Class<?> memoryLayoutCls = Class.forName("java.lang.foreign.MemoryLayout");
                Class<?> memoryLayoutArrayCls = Class.forName("[Ljava.lang.foreign.MemoryLayout;");
                Class<?> valueLayoutCls = Class.forName("java.lang.foreign.ValueLayout");
                Class<?> valueLayoutAddressCls = Class.forName("java.lang.foreign.AddressLayout");
                MethodHandle addressLayoutGetter = lookup.findStaticGetter(
                        valueLayoutCls, "ADDRESS", valueLayoutAddressCls);
                MethodHandle byteSize = lookup.findVirtual(valueLayoutAddressCls, "byteSize", methodType(long.class));
                MethodHandle byteSizeOfAddress = MethodHandles.foldArguments(byteSize, addressLayoutGetter);
                long addressSize = (long) byteSizeOfAddress.invokeExact();
                if (addressSize != Long.BYTES) {
                    throw new UnsupportedOperationException(
                            "Linking to malloc and free is only supported on 64-bit platforms.");
                }

                // Finally, we create three method handles, for malloc, free, and for wrapping an address in a
                // ByteBuffer. Effectively, we need the equivalent of these three code snippets:
                //
                //        MemorySegment mallocPtr = Linker.nativeLinker().defaultLookup().find("malloc").get();
                //        MethodHandle malloc = Linker.nativeLinker().downcallHandle(
                //                mallocPtr, FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG));
                //
                //        MemorySegment freePtr = Linker.nativeLinker().defaultLookup().find("free").get();
                //        MethodHandle free = Linker.nativeLinker().downcallHandle(
                //                freePtr, FunctionDescriptor.ofVoid(ValueLayout.JAVA_LONG));
                //

Frequently Asked Questions

What is the CleanerJava24Linker class?
CleanerJava24Linker is a class in the netty codebase, defined in common/src/main/java/io/netty/util/internal/CleanerJava24Linker.java.
Where is CleanerJava24Linker defined?
CleanerJava24Linker is defined in common/src/main/java/io/netty/util/internal/CleanerJava24Linker.java at line 28.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free