JAVA ( 一 )虚拟机的内存结构

JVM是Java虚拟机,运行在操作系统之上,所以JAVA 有着 一次编译,到处运行的功能

JVM的内存分下面几个部分

1,程序计数器 线程私有的,每个线程都有自己的程序计数器。  是当前线程正常执行的那条字节码指令的地址,若当前线程执行的是一个地址方法,

那么此时程序计算器未Undefined,不需要程序员维护的。

2, java虚拟机栈  线程私有的   该区域也是我们常说的JMM(java内存模型?线程安全),每个方法在执行的时候,都会创建一个栈,

用来存储自己的局部变量,操作数栈,方法出口等信息,局部变量包括基本数据类型,引用类型,returnAddress?等,

局部变量大小在编译加载就确定的,进入方法后是大小固定的。在方法运行期间不会改变局部变量表的大小。

   在程序开发的时候,调试或抛异常的时候,可以栈看到方法调用顺序。

如下调试可以看出,最底下是main,再调用 funa,最后func,异常也是一样输出。这个就是栈。

当你方法调方法太多,比如我们经常递归调用自己,死循环了,栈空间就是不足,报StackOverflowError

栈也可以申请更多的空间,申请不到报 OutOfMemoryError。

3,本地方法栈,线程私有的,本地方法栈跟java虚拟机栈的差不多,只是它的方法都是JDK自带的方法,可能是C,C++写的。

4,堆,    线程共享的,用来存放实例化的对象(由于现在有了逃逸分析技术,也可以将对象分配在栈上?),垃圾回收的主要

操作区域,分为老年代和新生代,新对象一般都会在新生代,对象超过一定设定的大小,会直接分配在老年代,新生代会通过一定的算法分配到老年代,比如计数法等,堆空间不足时会出现OutOfMemoryError异常。

5,方法区, 线程共享,存放被加载的类的信息(是不是可以理解为什么程序启动第一次跑会慢点的原因),常量,静态变量以及即时编译后的代码等数据,方法区中还有块区域存放运行时常量,因为"aaaa"是final修饰的类,所以字符对象都会存在这里,

String对象的intern也是将对象变成常量存在常量池。方法区空间不足时会抛出OutOfMemoryError异常

è¿éåå¾çæè¿°

除了Java虚拟机规定的这几块区域以外呢,还存在一个堆外内存,即直接内存,直接内存能减少IO时的内存复制了,实现零拷贝,而且没有GC,减少了垃圾回收的工作,加快了复制的速度,该区域也难以控制,如果内存泄漏很难排查。

猜你喜欢

转载自blog.csdn.net/shrek11/article/details/89676146