- 先说重点:
- 对象在堆区
- 方法在栈区
- 变量在方法区,常量池在方法区
- 为什么要了解Java 虚拟机 ?
这个问题一直困惑了我很长一段时间,其实在我们开发的过程中,即使我们不了解JVM也能正常的开发,但是当遇到如何优化代码,如何调优程序性能,当我们碰到内存泄漏的时候如何去解决,如何正确使用GC即垃圾回收等问题时,我们想有更好的解决办法,我们就必须去了解Java虚拟机,工欲善其事,必先利其器。Java虚拟机是程序运行最基础的存在。
- 了解Java JVM
想了解Java虚拟机必须要先了解Java内存分布,下面盗一下《深入理解Java虚拟机》书中的图:
我们从图中可以看到程序在运行时在内存中分布有五块区域,下面分别简单说明一下各个区域的作用:
- 程序计数器:程序计数器又叫线程计数器,每一个线程都有一个线程计数器,为什么要设置这个线程计数器,这里很重要,JVM在运行多线程的时候是通过线程轮流切换分配执行时间来实现的,无论在任何时刻,每个处理器都只会执行一个线程中的指令,在线程之间切换的时候,JVM要记录线程执行到了哪一行,而这个线程计数器就起到记录哪一行的作用。
- 虚拟机栈:平时我们说的栈也就是指的是Java虚拟机栈,和程序计数器一样,虚拟机栈也是线程私有的,在项目中,每个方法在执行的同时都会创建一个栈帧(栈帧是编译器在调用函数时涉及到的调用信息的记录单元),用于存储局部变量表,操作栈数,动态链接,方法出入口等信息。每个方法从调用到执行完成的过程就是一个栈帧从进栈到出栈的过程。
- 本地方法栈:与虚拟机栈基本相同,唯一的区别是虚拟机栈执行Java方法,而本地方法栈执行native方法。
- 方法区:方法区是线程共享的区域,存储虚拟机加载的类信息、静态变量、常量、即时编译的代码等。
- 堆:Java堆也是线程共享的一块区域,并且是JVM管理的内存中最大的一块,主要存储对象的实例。
- 在什么情况下JVM会出现内存溢出
原则:其实Java虚拟机也遵循万物规律--满则溢
- 如果当Java虚拟机允许动态扩展Java虚拟机栈内存的时候,当扩展到没有分配到内存的时候,就会报OutOfMemoryError异常,也就是内存溢出。扩展:当Java虚拟机在分配内存时,无法分配程序申请的内存时,会出现内存泄漏,一次内存泄漏影响不大,但随着内存泄漏的累积就会出现内存溢出;
- 当堆中没有内存完成对象实例分配,或者堆内存无法扩展的时候,将会抛出OutOfMemoryError异常;当前虚拟机都是可以扩展的;
- 当Java虚拟机无法满足方法区的内存分布的时候,也会抛出OutOfMemoryError异常;
到此为止我所理解的JVM相关知识就这些了,希望各位大大指正和补充。谢谢!