直接内存
1. 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域
 2. 直接内存是在Java堆外、直接向系统申请的内存区间
 3. 来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存
 4. 通常,访问直接内存的速度会优于Java堆,即读写性能高
 5. 处于性能考虑,读写操作频繁的场合会考虑使用直接内存
 6. Java的NIO库允许Java程序使用直接内存,用于数据缓冲区
 7. 由于直接内存在Java堆外,因此它的大小不会直接受限于-Xmx指定的最大堆大小,但是系统内存是有限的,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存。
 8. 直接内存的大小可以通过MaxDirectMemorySize设置,如果不指定,则默认于堆的最大值-Xmx参数值一致
缺点:
分配回收成本较高
不受JVM内存回收管理
public class BufferTest {private static final int BUFFER=1024*1024*1024;//1GBpublic static void main(String[] args) {
//        直接分配内存空间ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);System.out.println("直接内存分配完毕,请求指示!");Scanner scanner=new Scanner(System.in);scanner.next();System.out.println("直接内存开始释放");byteBuffer =null;System.gc();scanner.next();}
}

死锁
public class TestDeadLock implements Runnable {    public int flag = 1;    static Object o1 = new Object(), o2 = new Object();public void run() {    System.out.println("flag=" + flag);  if (flag == 1) {    synchronized (o1) {    try {    Thread.sleep(500);    } catch (Exception e) {    e.printStackTrace();    }    synchronized (o2) {    System.out.println("1");  }    }    }    if (flag == 0) {    synchronized (o2) {    try {    Thread.sleep(500);    } catch (Exception e) {    e.printStackTrace();    }    synchronized (o1) {    System.out.println("0");  }    }    }    
}当flag为1时,线程首选获取o1锁,休眠500毫秒,然后尝试获取o2的锁,如果成功过,则打印"1".
当flag为2时,线程首选获取o2锁,休眠500毫秒,然后尝试获取o1的锁,如果成功过,则打印"0".
由于td1和flag为1,它首先获取了o1的锁,并休眠500毫秒。在td1休眠期间,td2开始执行并获取了o2的锁。当td1醒来兵尝试获取o2的锁时,它会被阻塞,因为o2的锁已经被td2持有,同样地,当td2醒来兵尝试获取o1的锁时,因为o1的锁已经被td1持有,这样,两个线程都陷入了等待状态,形成了死锁
为了避免死锁,可以采取以下策略:

方法句柄
静态方法句柄
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;public class MethodHandleExample {public static void staticMethod(){System.out.println("static method called");}public static void main(String[] args) throws Throwable {
//        获取当前类的查找器MethodHandles.Lookup lookup=MethodHandles.lookup();
//        创建静态方法句柄MethodHandle methodHandle=lookup.findStatic(MethodHandleExample.class,"staticMethod", MethodType.methodType(void.class));
//        调用方法句柄methodHandle.invoke(); // static method called}
}实例方法句柄
import java.lang.invoke.MethodHandle;  
import java.lang.invoke.MethodHandles;  
import java.lang.invoke.MethodType;  public class MethodHandleExample {  public void instanceMethod() {  System.out.println("Instance method called");  }  public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException {  // 创建类的实例  MethodHandleExample example = new MethodHandleExample();  // 获取当前类的查找器  MethodHandles.Lookup lookup = MethodHandles.lookup();  // 创建实例方法句柄  MethodHandle methodHandle = lookup.findVirtual(MethodHandleExample.class, "instanceMethod", MethodType.methodType(void.class));  // 绑定实例并调用方法句柄  methodHandle.bindTo(example).invoke();  }  
}
 构造函数句柄
 
import java.lang.invoke.MethodHandle;  
import java.lang.invoke.MethodHandles;  
import java.lang.invoke.MethodType;  public class MethodHandleExample {  public MethodHandleExample() {  System.out.println("Constructor called");  }  public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException {  // 获取当前类的查找器  MethodHandles.Lookup lookup = MethodHandles.lookup();  // 创建构造函数句柄  MethodHandle constructorHandle = lookup.findConstructor(MethodHandleExample.class, MethodType.methodType(void.class));  // 调用构造函数句柄创建实例  MethodHandleExample example = (MethodHandleExample) constructorHandle.invoke();  }  
}方法句柄优势
方法句柄比传统的Java反射API更快,因为他们直接利用了JVM内部机制
方法句柄可以绑定到各种类型的方法上,包括私有方法和构造函数
方法句柄的访问控制更加细粒度,可以在运行时动态调整权限
public class Test {class GrandFather{void thinking(){System.out.println("GrandFather ");}}class Father extends GrandFather{void thinking(){System.out.println("Father");}}class Son extends Father{void thinking(){try {MethodType mt=MethodType.methodType(void.class);//            获取当前类的查找器MethodHandles.Lookup lookup=MethodHandles.lookup();
//            创建句柄MethodHandle mh=lookup.findSpecial(GrandFather.class,"thinking",mt,getClass());mh.invoke(this);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (Throwable e) {throw new RuntimeException(e);}}}public static void main(String[] args) {(new Test().new Son()).thinking();}
}public class Test {class GrandFather{void thinking(){System.out.println("GrandFather ");}}class Father extends GrandFather{void thinking(){System.out.println("Father");}}class Son extends Father{void thinking(){try {MethodType mt=MethodType.methodType(void.class);// 反射,绕过保护机制Field lookupImpl =MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");lookupImpl.setAccessible(true);
//            获取当前类的查找器
//                MethodHandles.Lookup lookup=MethodHandles.lookup();
//            创建句柄MethodHandle mh=((MethodHandles.Lookup)lookupImpl.get(null)).findSpecial(GrandFather.class,"thinking",mt,GrandFather.class);mh.invoke(this);  //GrandFather} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (Throwable e) {throw new RuntimeException(e);}}}public static void main(String[] args) {(new Test().new Son()).thinking();}
}