java的运行时内存主要包含以下几个区域:
1、程序计数器:线程独有,是最少的内存区域,没有规定任何的异常抛出。
2、java 栈 :线程独有,分别有java虚拟机栈和本地方法栈(执行native方法) hotspot已经合并这两个区域。这个区域可以抛两中异常outofmemoryerror(动态扩展内存,但也申请不到内存,例如无线创建线程) 和stackoverflowerror(超出规定的栈大小),栈在执行方法时会创建一个栈帧,一个方法对应一个栈帧,栈帧包含操作数栈(用户存储计算参数和计算结果,在方法调用时,也用来准备调用方法的的参数以及接收方法的返回结果)、局部变量表,表的大小在编译期间已经确定大小,局部变量表的最少单位为slot(根据不同机器规定的大小不一样)。
3、java堆 全局共享,要实现自动内存管理 会出现outofmemoryerror异常
4、方法区和常量池,方法区存放常量、静态变量、方法信息、编译器产生的代码信息(这个区域不要实现自动内存管理),可能出现outofmemoryerror
常量池是方法区的一个部分。作用是存储java类文件常量池中的符号信息
5、永久代:
在JDK1.2到JDK1.6 hotSpot使用永久代实现方法区 ,java7之后就没有永久代的概念,改用java heap来实现。
6、intern 方法的意思是从字符串常量池拿区字符串地址,比如:String a = new String(“123”).intern() a == “123” 是返回true的,如果字符串池没有,就把当前的字符串地址放进字符串池当中。eg:String a = “123”; 其实是创建了一个123的字符串对象,并且发这个对象放到字符串池中,如果再有String b = “123”;这个时候使用的其实是字符串池中的对象,所以 a == b 必然是ture。 另外一下代码,在java6 和java 7是有区别的
public class Test {
public static void main(String[] args) {
// String a = "123";
String b = new String("123");
String c = new StringBuilder("abc").append("def").toString();
System.out.println(b.intern() == b);
System.out.println(c.intern() == c);//1.7返回ture,1.6返回false
因为java7和java6的常量池的实现区域不一样了,java6是在永久代,而java7已经在java heap中实现,上面的例子,abcdef这个字符串是在常量池中没有,所以就把c对象的地址放到常量池中,而1.7的话就是直接把堆中地址返回就行,所以返回true,而java6 其实是要在永久代这块区域重新建一个对象,返回一个地址,所以必然和c对象的地址不一样。