`

JAVA内存

    博客分类:
  • JAVA
 
阅读更多

一:Java虚拟机和Java内存区域概念

java虚拟机运行时数据区:

有一些区域时全局共享的,随着虚拟机启动而创建,随着虚拟机退出而销毁,一些区域时线程私有的,随着线程开始和结束而创建和销毁。

 

HotSpot 是主流虚拟机 

 

运行时数据区的划分

1、程序计数器

2、java堆:线程共享

3、java栈

4、本地方法栈

5、方法区:线程共享

 

四、内存泄露和内存溢出

 

1: 内存泄露 程序申请内存后,无法释放以申请的内存空间

2: 内存溢出 程序申请内存时,没有提供足够的内存空间

 

1、程序计数器:最小空间,线程私有

可以看作一个指针,他指着当前运行程序(字节码指令的行号指示器)正在运行的那一行代码 

 

如果正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址。

 

如果正在执行的是Native方法,计数器为null。

 

唯一一个不会有OutOfMemory情况的区域

 

2、java虚拟机栈和方法栈 :区别java虚拟机栈是java虚拟机执行字节码服务的,而本方法栈是为了执行Native方法服务的 

 

   (1)java虚拟机栈,线程私有,可能会出现OutOfMemoryError和StackOverflowError异常

描述的是java方法执行时内存概念模型,每个方法在执行时,都会创建一个栈祯

如果线程请求的栈深度大于java虚拟机允许的最大深度,就会StackOverflowError

不断地递归方法时,就会产生StackOverflowError

 

如果java虚拟机栈被设置为可以动态扩展,而在动态扩展时,无法申请到足够的内存,就是OutOfMemoryError

不断地创建线程时,就会产生OutOfMemoryError

 

    (2)java本地方法栈,支撑Native方法

 

    (3)栈帧:java虚拟机栈中存储的内容,它被用于存储数据和部分过程结果,同时也被用来处理动态链接,方法返回值和异常分派;一个完整的栈祯包含,局部变量表、操作数栈、动态连接信息、方法正常完成和异常完成信息。

       栈祯的分配多大的内存是在编译时

      

       局部变量表:是一组变量值的存储空间,用于存储方法,参数 ,方法内部变量

                            由若干个slot组成,长度由编译期决定

                            单个slot可以存储一个类型为boolean、byte、char、short、float、reference 和 retrunAddress的数据

         两个slot可以存储long和double

         重要:reference类型 : 表示对像实例的引用,java虚拟机可以通过一个reference完成两件事件,可              以在堆中查到实例,还可以方法区查到类型信息

 

        操作数栈:有若干个Entry组成

                          在方法执行过程中,操作数栈用于存放方法计算参数和计算结果。

        

        查看java文件的字节码:javap -version Test

 

        局部变量表和操作数栈工作方式,两者随着程序计数器指针执行,作入栈出栈操作。

 

         

 3:java堆:全局共享,最大,存java对象,可能会出现OutOfMemoryError

 

jvms 明确要求该区域需要实现自动内存管理,即常说的GC,但并不限制采用哪种算法和技术去实现。

 

java堆中对象的实例数据,在对象实例数据中,预留一个指针,指向方法区中的对象类型数据

 

如果实际所需的堆超过了自动内存管理系统提供的最大容量,那java虚拟机将会抛出一个OutOfMemoryError

 

当不断的创建对象,并且对象不会被销毁时,就可以内存泄露

 

4:方法区和运行常量池

方法区:共享,存储java类的信息(在类中声明的方法,常量,静态变量,字段)

运行常量池(是方法区的一部分):属于方法区一部分,存储java类文件(class)常量池中的符号信息

 

永久代与方法区

在jdk1.2-jdk1.6,hotspot 使用永久代实现方法区

jdk1.7 hotspot开始了移除永久代的计划

符号表被移到Native heap中

字符串常量和类的静态引用被移到java heap中

常量池的大小设置:permsize = 10M maxPerSize=10M 

 

 

 5:直接内存的概念和特征

并非标准的java运行时内存区域

 

加入NIO被引入,目的是避免在java堆和Native堆中来回复制数据带来的性能损耗

 

OutOfMemoryError 抛出时不会有明细的提示,而堆内存溢出或者常量池溢出都会有明显的提示。

 

6: 对象创建

1、当虚拟机遇到一条new指令时,先检查这个指令是否能在常量池中定位一个类的符号引用

2、 如果没有定位到,先执行类加载,然后在为新生对像分配空间,空间大小有类加载决定的(分配空间方式,指针碰撞和空闲列表)

3、将分配到的内存空间都初始化为零值

 

7、对像在内存中存储的布局可以分为3部分

存储对象自身的运行时数据

类型指针

对齐填充

 

8、对象的访问定位

java栈 (reference)-》 java 堆(句柄)-》可以通过句柄找到对象的实列数据和在方法区找到对象类型数据

 

java栈(reference)-》java堆(对象的实列数据)-》再由对象实列头找到对象类型数据

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics