对于java程序员来说,在虚拟机的自动内存管理机制下,不需要显式的对new出来的对象进行free和delete操作。但是了解java是如何进行内存分配的,对我们排查错误具有极大的帮助。
今天笔者按照所看的书上的内容和自己的理解来简单的谈一下java的内存分配问题。关于java运行时的数据区域,主要涉及以下几个:
程序计数器:它主要存储的是当期线程所执行的字节码的行号等信息,然后字节码解释器根据计数器中存储的内容来选取下一条需要执行的字节码指。因此,可以看出,每条线程都有一个独立的程序计数器,它是线程私有的。
java虚拟机栈和本地方法栈:这两个我放在一起来说,是因为他们两个的作用非常类似,区别不过是虚拟机栈是为虚拟执行java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务(就是这个方法是用C++/C来实现的,编译成dll供java调用的)。java虚拟机栈也是线程私有的,与线程的生命周期相同。程序中的每个方法在执行的时候都会创建一个栈帧,里面存放了局部变量表、操作栈、动态连接、方法出口信息,局部变量表里存的是程序中基本类型的数据,局部变量和对象的引用等等。每一个方法从调用到完成的过程,就是相应的栈帧在虚拟机栈中压栈和出栈的过程。
java堆:java堆是被所有线程共享的一块区域,它的作用就是存放几乎所有对象的实例,也就是存放new产生的数据(当然还有一些其他技术可以让new出来的数据存放到栈上或其他地方)。
方法区:它也是所有线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量等数据。
运行时常量池:在方法区里面又划分了一块区域为运行时常量池,用于存放程序中的一切常量,包含代码中所定义的各种基本类型(如int,long等等)和对象型(如String及数组)的常量值(final)。每个Class文件都会有一个常量池,存放的是常量值的符号引用,当类加载后,会将这部分信息存放到运行时常量池,等到类的解析完成之后,会将符号引用替换成直接引用,与全局字符串池(String pool)中的值保持一致。