看了博主“一杯凉茶”一篇对java内存详解的文章后,虚心学习,并记录下来 ,以便日后再来温故。
一,运行时数据区
1、程序计数器
当前线程所执行的字节码行号指示器,字节码解释器工作依赖计数器控制完成,通过执行线程行号记录,让线程轮流切换,使各条线程之间互不影响。
线程私有,生命周期与线程相同,随JVM启动而生,JVM关闭而死。线程执行Java方法时,记录其正在执行的虚拟机字节码指令地址,
1、方法区
在Java虚拟机中,关于被装载类型的信息存储在一个逻辑上被称为方法区的内存中。当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件----一个线性二进制数据流----然后将它传输到虚拟机中,紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区。该类型中的类(静态)变量同样也存储在方法区中。
由于所有线程都共享方法区,因此它们对方法区数据的访问必须被设计为是线程安全的。比如,假设同时有两个线程都企图访问一个名为Lava的类,而这个类还没有被装载,那么,这时只应该有一个线程去装载它,而另一个线程只能等待。
对每个装载的类型(类或接口),虚拟机都会在方法区中存储以下类型信息:
1、这个类型的全限定名
2、这个类型的直接超类的全限定名(除非这个类型是java.lang.Object,他没有超类)
3、这个类型是类类型还是接口类型
4、这个类型的访问修饰符(public、abstract或final的某个子集)
5、任何直接超接口的全限定名的有序列表
除了上述基本类型信息外,虚拟机还得为每个被装载的类型存储以下信息:
1、该类型的常量池
2、字段信息
3、方法信息
4、除了常量以外的所有类(静态)变量
5、一个到类ClassLoader的引用
6、一个到Class类的引用
1.1常量池
虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合,包括直接常量(String、integer和float point常量)和对其他类型、字段和方法符号的引用。池中的数据项就像数组一样是通过索引访问的,因为常量池存储了相应类型所用到的所有类型、字段和方法的符号引用,所以它在Java程序的动态连接中起着核心作用,常量池在后面会详解。
1.2字段信息
1、字段名
2、字段的类型
3、字段的修饰符(public、private、protected、static、final、volatile、transient的某个子集)
1.3方法信息
对于类型中声明的每一个方法,方法区中必须保存下面的信息。和字段信息一样,这些方法在类或接口中的声名顺序也必须保存。下面是方法信息的清单:
1、方法名
2、方法的返回类型(或void)
3、方法参数的数量和类型(按声明顺序)
4、方法的修饰符(public、private、protected、static、final、synchronized、native、abstract的某个子集)
除上述清单列出的条目之外,如果某个方法不是抽象的和本地的,它还必须保存下列的信息:
1、方法的字节码(bytecodes)
2、操作数栈和该方法的栈帧中的局部变量区的大小
3、异常表
1.4类(静态)变量
类变量是由所有实例共享的,但是即使没有任何类实例,它也可以被访问。这些变量只与类有关----而非 类的实例。因此它们总是作为类型信息的一部分而存储在方法区。
而编译时常量(就是那些用final声明以及用编译时已知的值初始化的类变量)则和一般的类变量的处理方式不同,每个使用编译时常量的类型都会复制它的所有常量到自己的常量池中或嵌入到它的字节码流中。作为常量池或字节码流的一部分,编译时常量保存在方法区中----就和一般的类变量一样。
1.5指向ClassLoader类的引用
每个类型被装载的时候,虚拟机必须跟踪它是由启动类装载器还是由用户自定义类装载器装载的。如果是用户自定义类装载器的,那么虚拟机必须在类型信息中存储对该装载器的引用。
虚拟机会在动态连接期间使用这个信息。当某个类型引用另一个类型的时候,虚拟请求装载发起引用类型的类装载器来装载被引用的类型。这个动态连接的过程,对于虚拟机分离命名空间的方式也是至关重要的。为了能够正确的执行动态连接以及维护多个命名空间,虚拟机需要在方法表中得知每个类都是由哪个类装载器装载的。
1.6指向Class类的引用
对于每个被装载的类型(不管是类还是接口),虚拟机都会相应的为它创建一个java.lang.Class类的实例,而且虚拟机还必须以某种方式把这个实例和存储在方法区中的类型数据关联起来。
在你的Java程序中,你可以得到并使用指向Class对象的引用。Class类中一个静态方法可以让用户得到任何已装载的类的Class实例的引用。
// A method declared in class java.lang.Class;
public static Class forName(String classname);