java内存区域

 

 程序计数器,虚拟机栈,本地方法栈的生命周期随着线程的开始和死亡。

 年轻代一般采用标记复制算法来进行对象的回收,因为年轻代大多数是死亡对象,这种算法效率更高,但是会浪费一部分内存。

 年老代因为大部分对象都是存活对象,一般采用标记整理,其中CMS采用标记清理,后续来进行整理,是为了提高并行的效率。

对象创建过程:

java中对象的引用方式有四种:

1  强引用

2  软引用:当内存不足,才进行回收

3  弱应用:不管内存是否足够,下一次就回收

4 虚引用:用来进行回收通知

对象可达性:是根据对象是否被gc roots应用 , gc roots:静态变量,常量,栈桢中的本地变量,本地方法栈jni

java内存分类:栈内存和堆内存

      堆内存:方法区和堆内存,其中方法区是作为堆内存的一个逻辑区域,又称为非堆,目的是与java堆内存区分开来。方法区和堆内存是所有线程共享的的区域。

      其中栈内存又分为:虚拟机栈,本地方法栈,程序计数器

      虚拟机栈:描述java方法的内存模型,在执行java方法的时候,都会创建一个栈帧,这个栈帧保存局部变量表,操作数栈,动态链接,方法出口,局部变量表保存的是在编译时可知的各种基本数据类型(int,double,float,long,boolean,char, btye),对象的引用。

      本地方法栈:使用jna jni技术调用的c/c++写的函数。

      程序计数器:记录java编译后的字节码执行时的行号。

      方法区:存储类信息,静态变量,常量,编译后的代码,其中比较重要的是运行时常量池,里面存储的时在编译时就已经确认的各种字面常量。

对象创建过程:

      当虚拟机遇到一条new 命令的时候,先去常量池去查找这个类的符号引用,然后检查这个符号引用代表的类是否已经加载,初始化,如果没有,就去找.class执行类的加载过程,在类加载完成后,虚拟机将为对象分配内存,分配内存有两种方法:一种是指针碰撞(有个指针把空闲去和非空闲去隔开,对象分配内存时,只需要挪动指针的位置就可以了,挪动的距离就是对象的大小)。还有一种方式时空闲列表(由于内存空闲区,是一段一段的,并不是连续的,虚拟机维护一个空闲列表,当需要为对象分配内存的时候,虚拟机从空闲列表中找到一块合适的内存给它)。具体采用那一种方式,取决与java堆中的内存是否连续,而java堆中的内存是否连续,在于载虚拟机进行垃圾回收的时候,是否进行内存整理。

     如果多个线程同时需要这快内存解决办法:一种载内存分配时进行加锁操作,一种是为每个线程分配一块内存,当这块内存用完,并需要新的线程内存才进行锁定操作,提高了效率。

     内存分配完了以后,需要对对象成员进行初始化操作,主要的是要设置对象头信息(包括对象的哈希码,对象分代信息,对象是那个类的实例等信息)。

对象的内存布局:主要由三部分组成(对象头,实例数据,内存需要对齐的填充)其中实例数据是真正有效的数据。对齐填充一般用于内存对齐,没有实际的意义。

常用的虚拟机参数设置:-Xmx 虚拟机最大分配内存  -Xms 初始化虚拟机的内存,一般设置成一样,避免程序内存增长,又为虚拟机进行内存分配,避免自动扩展。

-Xss 本地方法栈容量

java堆内存细分:年轻代和年老代,年轻代又分为 eden 区 from survivor 区 to survivor区  

                               

原文地址:https://www.cnblogs.com/xqGo/p/3987215.html