Java程序里面有很多的东西,变量,方法,对象实例,方法里面的变量,静态变量,下一次要执行的地址……
内存其实就是放这些东西,而这些东西根据存活时间长短和功能放在这个内存的不同小区域里,这些个小区域又根据它们里面放的东西的不同而叫不同的名字。
Java的内存,有堆区、栈区、方法区、程序计数器这四类。
1、程序计数器:主要用来记录下一次要执行的地址,它是线程私有的。
学过操作系统的该知道,其实没有所谓的同一时刻既可以运行这个东西,又可以运行那个东西,只不过是计算机处理太快了,所以我们感觉同一时刻执行了很多东西而已。
因为CPU只有一个,那下次要运行的地方就得记住了,多个线程之间通过时间片轮询来抢夺CPU这个资源,然后执行本线程之类内的东西,谁抢到了,谁的线程就又跑起来了,那么就用程序计数器来记录下一次要执行的地址,所以它是线程私有的,而且功能就是用来记录下一次要执行的地方。
如果执行的是Java方法,则计数器记录的是Java字节码地址,如果是Native方法(下次)。则计数器是空的。
2、方法区:它是所有线程共享的,放的东西是已经被虚拟机加载的类信息,常量,static代码,可以叫做永久代,一般是很少回收这个区域的,只有当一个类的定义信息不会被使用时才会对它进行回收。
这里容易出现对比:静态代码块,普通代码块,构造代码块三个之间的对比(下次)。
3、堆区:它也是所有线程共享的,存放的主要是所有对象实例和数组,是垃圾回收的主要区域,可以分为新生代和老年代。
4、栈区:可以分为Java虚拟机栈和本地方法栈。
(1)Java虚拟机栈:是线程私有的,生命周期与线程是相同的。
(2)本地方法栈:方法在执行的时候都会创建一个栈帧,用来存放局部变量,操作栈,动态链接,方法出口等。
(3)这两个栈其实功能都是相似的,主要区别在于本地方法栈是管理本地用C实现的方法。
(4)stackoverflow和outofmemory的区别:栈大小是可以固定的,也是可以变化的,当你请求的栈大小超过了这个栈实际大小,就会出现Stack Overflow,当你请求的栈大小通过扩展栈容量也无法实现的时候就会出现outofmemory。