Java虚拟机全称:java virtual machine;是Java开发语言中,用来运行Java字节码文件的平台;通俗的讲,就是一个程序。它提供对Java字节码的解释及运行,从而使Java语言能独立于各个系统平台。
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁时间。Java虚拟机所管理的内存包括以下几个运行时数据区域:
1)程序计数器: 可以看作是当前线程所之行的字节码的行号指示器。字节码解释器就是通过改变计数器的值来选取下一条需要执行的字节码指令。Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令。因此每个线程都需要一个独立的程序计数器。
2)Java虚拟栈:与程序计数器一样,也是线程私有的。生命周期和线程相同。
3)本地方法栈:为虚拟机使用到的Native方法服务。
4)Java堆:Java堆十倍所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域用于存放对象实例。Java堆是垃圾收集器管理的主要区域。
5)方法区:同样也是所有线程共享的区域,用于存储已被虚拟机加载的数据。
6)运行时常量池:是方法区的一部分。用于存放编译期生成的各种字面量和符号引用。
7)直接内存:
虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,则必须先执行相应的类加载过程。(p45)
线程安全与非线程安全
非线程安全是指多线程操作同一个对象可能会出现问题。而线程安全则是多线程操作同一个对象不会有问题。线程安全必须要使用很多synchronized关键字来同步控制,所以必然会导致性能的降低。所以在使用的时候,如果是多个线程操作同一个对象,那么使用线程安全的Vector;否则,就使用效率更高的ArrayList。
非线程安全!=不安全
对象的内存布局
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、示例数据(Instance Data)和对齐填充(Padding)。
对象的访问定位:
1)使用句柄访问:Java堆中划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址。而句柄中包含了对象示例数据和类型数据各自的具体地址信息;
优势:在对象被移动时只会改变句柄中的示例数据指针,而reference本身不需要修改。
2)使用直接指针访问:此时reference中存储的就是对象地址。
优势:速度快,节省了一次指针定位的时间开销。
OutOfMemoryError异常:
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生该异常的可能。
I)Java堆溢出:Java堆用于存储对象实例
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常;
如果虚拟机在扩展时无法申请到足够的内存空间,将抛出OutOfMemoryError异常。