反编译字节码文件
javap -v Demo.class
通过类的权限名获取定义此类的二进制字节流
将这个字节流所代表的静态存储数据转化为方法区的运行时数据结构
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
扩展:为什么要用内部静态类实现单例模式是线程安全的?
//基于类初始化的线程安全的单例
class SingleTon{
private SingleTon(){}
// 1. 静态内部类不引用时不加载,避免内存浪费。
// 2. 如果同时被多个线程引用,JVM会保证只有一个线程执行方法,进行类变量的赋值和静态代码块的运行
private static class InnerClass{
private static SingleTon instance= new SingleTon();
}
public static SingleTon getInstance(){//如果没有到这里,那么不会加载上面的内部类
return InnerClass.instance; //这里将导致InstanceHolder类被初始化
}
}
静态内部类的优点是:
外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。具体来说当SingleTon第一次被加载时,并不需要去加载InnerClass,只有当getInstance()方法第一次被调用时,使用INSTANCE的时候,才会导致虚拟机加载InnerClass类。这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。
怎么实现的?
方法:这不是由程序员写的程序,而是根据代码由javac编译器生成的。它是由类里面所有的类变量的赋值动作和静态代码块组成的。JVM内部会保证一个类的方法在多线程环境下被正确的加锁同步,也就是说如果多个线程同时去进行“类的初始化”,那么只有一个线程会去执行类的方法,其他的线程都要阻塞等待,直到这个线程执行完方法。然后执行完方法后,其他线程唤醒,但是不会再进入()方法。也就是说同一个加载器下,一个类型只会初始化一次。