01-Java内存区域

一、运行时数据区域

1、各个区域的作用

1.1、程序计数器:当前线程执行的字节码的行号指示器,占用空间小,也无法干涉

1.2、堆:几乎所有对象都分配在这里,也是垃圾回收发生的主要区域,可用以下参数调整

 ①、-Xms: 堆的最小值

 ②、-Xmx: 堆的最大值

 ③、-Xmn: 新生代的大小

 ④、-XX: NewSize 新生代最小值

 ⑤、-XX: MaxNewSize 新生代最大值

 例如:-Xmx512m

1.3、栈:每个线程私有的,线程在运行时,在执行每个方法的时候都会打包成一个栈帧,存储了局部变量表,操作数栈,动态链接,方法出口等信息,然后放入栈。每个时刻正在执行的当前方法就对应着栈帧在虚拟机栈中入栈出栈的过程。

栈帧大小初始为1M,可用参数 -Xss调整大小,例如 -Xss256k

1.4、方法区:用于存储已经被虚拟机加载的类信息,常量("zdy","123"等),静态变量(static变量)等数据,可用以下参数调整:》》

jdk1.7及以前:-XX:PermSize -XX:MaxPermSize

jdk1.8及以后:-XX:MeetaspaceSize

1.5、运行时常量池:下面是各个版本内存区域变化》

①、1.6 JDK 运行时常量池在方法区

②、1.7 JDK 运行时常量池在堆

③、1.8 JDK 运行时常量池在元数据区

 

2、直接内存

2.1、不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域

2.2、如果使用了NIO,这块区域会被频繁使用,在java堆内可以用directByteBuffer对象直接引用并操作

2.3、这块内存不受java堆大小限制,但受本机总内存的限制,可以通过 -XX:MaxDirectMemorySize来设置(默认与堆内存最大值一样),所以也会出现OOM异常。

 

二、深入辨析堆和栈

1、功能

1.1、以栈帧的方式存储方法调用的过程,并存储方法调用过程中基本基础类型的变量(int、short、long、byte、float、double、boolean、char等)以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放

1.2、而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。

2、线程独享还是共享

2.1、栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能再其所属线程中可见,即栈内存可以理解成线程的私有内存。

2.2、堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。

3、空间大小

3.1、栈的内存要远远小于堆内存

 

三、方法的出入栈

1、栈帧

一个方法的调用,就会在栈上分配一个栈帧

2、栈上分配

虚拟机提供的一种优化技术,基本思想是,对于线程私有的对象,将它打散分配在栈上,而不分配在堆上。好处是对象跟着方法调用自行毁灭,不需要进行垃圾回收,可以提高性能。

栈上分配需要的技术基础,逃逸分析。逃逸分析的目的是判断对象的作用域是否会逃逸出的方法体。注意,任何可以在多线程之间共享的对象,一定都属于逃逸对象

 

四、虚拟机中的对象

1、分配过程

虚拟机遇到一条new指令时,先执行相应的类加载过程,接下来虚拟机将为新生对象分配内存 。

为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。

如果Java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”。

猜你喜欢

转载自www.cnblogs.com/HvH95/p/11624529.html
今日推荐