package ffm; /// usr/bin/env jbang "$0" "$@" ; exit $?
//JAVA 11

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

/**
 * Java 11 approach for memory management.
 * <p>
 * This demonstrates the complexity involved before FFM API.
 * You need separate C files, compilation steps, and platform-specific builds.
 * </p>
 * <p>
 * Execute with JBang to force Java 11: jbang Java11NativeCalls.java
 * </p>
 */
public class Java11MemoryManagement {

    static void main(String[] args) throws Exception {
        System.out.println("=== Java 11 Memory Management Alternatives ===");

        // Approach 1: Direct ByteBuffers (Java 1.4+)
        demonstrateDirectByteBuffer();

        // Approach 2: sun.misc.Unsafe (Unofficial, dangerous)
        demonstrateUnsafe();

        // Approach 3: JNI (Complex, requires native code)
        demonstrateJNIApproach();
    }

    // APPROACH 1: Direct ByteBuffers
    // Pros: Official API, GC managed
    // Cons: Limited functionality, boxing overhead, no direct address access
    private static void demonstrateDirectByteBuffer() {
        System.out.println("\n1. Direct ByteBuffer Approach (Java 1.4+):");

        // Allocate off-heap memory
        ByteBuffer directBuffer = ByteBuffer.allocateDirect(5 * 4); // 5 integers
        directBuffer.order(ByteOrder.nativeOrder()); // Important for native interop

        // Convert to IntBuffer for easier integer operations
        IntBuffer intBuffer = directBuffer.asIntBuffer();

        // Write values (similar to FFM example)
        for (int i = 0; i < 5; i++) {
            intBuffer.put(i, i * 10);
        }

        // Read values back
        System.out.print("   Direct buffer contents: ");
        for (int i = 0; i < 5; i++) {
            int value = intBuffer.get(i);
            System.out.print(value + " ");
        }
        System.out.println();

        // LIMITATION: Cannot get actual memory address easily
        System.out.println("   Memory address: NOT ACCESSIBLE via public API");

        // LIMITATION: Memory cleanup is not deterministic
        // Buffer will be cleaned up by GC eventually, but you can't force it
        System.out.println("   Memory cleanup: Relies on GC (non-deterministic)");

        // Attempt to trigger cleanup (unreliable)
        directBuffer = null;
        System.gc(); // Hint to GC, but no guarantee
    }

    // APPROACH 2: sun.misc.Unsafe
    // Pros: Full memory control, direct addresses
    // Cons: Unofficial API, dangerous, being removed, requires reflection tricks
    private static void demonstrateUnsafe() throws Exception {
        System.out.println("\n2. sun.misc.Unsafe Approach (Unofficial, Dangerous):");

        // WARNING: This is highly discouraged and won't work in newer JVMs
        Unsafe unsafe = getUnsafeInstance();

        if (unsafe != null) {
            // Allocate native memory (5 integers = 20 bytes)
            long memoryAddress = unsafe.allocateMemory(5 * 4);

            try {
                // Write values directly to memory addresses
                for (int i = 0; i < 5; i++) {
                    unsafe.putInt(memoryAddress + (i * 4), i * 10);
                }

                // Read values back
                System.out.print("   Unsafe memory contents: ");
                for (int i = 0; i < 5; i++) {
                    int value = unsafe.getInt(memoryAddress + (i * 4));
                    System.out.print(value + " ");
                }
                System.out.println();

                // Can access the actual memory address
                System.out.println("   Memory address: 0x" +
                        Long.toHexString(memoryAddress).toUpperCase());

            } finally {
                // CRITICAL: Manual memory management required
                unsafe.freeMemory(memoryAddress);
                System.out.println("   Memory manually freed (error-prone!)");
            }
        } else {
            System.out.println("   Unsafe not accessible (blocked by newer JVMs)");
        }
    }

    // Reflection hack to get Unsafe instance
    private static Unsafe getUnsafeInstance() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            return null; // Blocked by security manager or module system
        }
    }

    // APPROACH 3: JNI (Java Native Interface)
    // Pros: Full native access
    // Cons: Requires C code, complex build process, platform-specific
    private static void demonstrateJNIApproach() {
        System.out.println("\n3. JNI Approach (Complex, requires native code):");

        System.out.println("   This would require:");
        System.out.println("   • Writing C/C++ code:");
        System.out.println("     JNIEXPORT jlong JNICALL Java_Demo_allocateMemory");
        System.out.println("     (JNIEnv *env, jobject obj, jint size) {");
        System.out.println("         return (jlong) malloc(size);");
        System.out.println("     }");
        System.out.println();
        System.out.println("   • Creating header files with javac -h");
        System.out.println("   • Compiling native library (.so/.dll/.dylib)");
        System.out.println("   • Managing library loading with System.loadLibrary()");
        System.out.println("   • Handling JNI type conversions and error checking");
        System.out.println("   • Platform-specific build scripts");
        System.out.println();
        System.out.println("   Result: 10x more code, complex build, platform issues");
    }
}

/*
COMPARISON WITH FFM API (Java 22+):

FFM Version (from our example):
    try (Arena arena = Arena.ofConfined()) {
        MemorySegment segment = arena.allocate(ValueLayout.JAVA_INT, 5);
        for (int i = 0; i < 5; i++) {
            segment.setAtIndex(ValueLayout.JAVA_INT, i, i * 10);
        }
        // Automatic cleanup when arena closes
    }

Key FFM advantages:
1. TYPE SAFETY: Compile-time checks vs runtime crashes
2. AUTOMATIC CLEANUP: try-with-resources vs manual memory management  
3. OFFICIAL API: Stable, supported vs unofficial/deprecated
4. DIRECT ADDRESSES: Easy access vs reflection hacks
5. NO NATIVE CODE: Pure Java vs C/C++ complexity
6. PERFORMANCE: Zero-copy operations vs marshalling overhead

The FFM API essentially gives you the power of Unsafe with the safety 
of official APIs and the convenience of automatic resource management.
*/