一个完整的Java程序运行过程会涉及以下内存区域:
一、寄存器
JVM内部虚拟寄存器,存取速度非常快,程序不可控制
二、java栈
保存方法内的局部变量的值,包括:
1、用来保存基本数据类型的值;
2、保存类的实例,即堆区对象的引用(指针)。也可以用来保存加载方法时的帧。
三、堆
用来存放动态产生的数据,Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的)
比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。
四、本地方法栈
本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一
五、方法区
1、方法区基本概念
方法区系统分配的一个内存逻辑区域,是一块所有线程共享的内存区域,用来存储类信息(类型信息可以理解为类的描述信息(类的全限定名,访问修饰符,字段,方法等) )、常量和静态变量
2、方法区特点
方法区的大小决定了系统可以包含多少个类,如果系统类太多,方法区内存不够会导致方法区溢出,虚拟机同样会抛出内存溢出信息。方法区特点:
1)方法区是线程安全的,由于所有的线程都共享方法区,所以方法区里的数据访问必须被设计成线程安全的。例如,假如同时有两个线程都企图访问方法区中的同一个类,而这个类还没有被装入jvm,那么只允许一个线程去装在它,而其他线程必须等待。
2)方法去的大小不必是固定的,jvm可根据应用需要动态调整,同时,方法区也不一定是连续的,方法区可以在一个堆(甚至是jvm自己的堆)中自由分配。
3)方法区也可被垃圾收集,当某个类不在被使用时,jvm将卸载这个类,进行垃圾收集
3、常量池
常量池即文件常量池,主要用来保存字面量和符号引用
1)JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。池中的数据和数组一样通过索引访问。
2)java中的常量池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复创建相等变量时节省了很多时间。常量池其实也就是一块内存空间,不同于使用new关键字创建的对象所在的堆空间。
java中的基本类型有:byte、short、char、int、long、boolean。其对应的包装类分别是:Byte、Short、Character、Integer、Long、Boolean。上边提到的这些包装类都实现了常量池技术,而两种浮点数类型的包装类则没有实现。另外,String类型也实现了常量池技术。
注意:
对于局部变量,如果是基本类型,会把值直接存储在栈;
如果是引用类型,比如String s = new String("william");会把其对象存储在堆,而把这个对象的引用(指针)存储在栈。
例如:
String s1 = new String(“william”);
String s2 = s1;
s1和s2同为这个字符串对象的实例,但是对象只有一个,存储在堆,而这两个引用存储在栈中