码迷,mamicode.com
首页 > 编程语言 > 详细

浅析Java的jvm上的内存位置的分配

时间:2018-06-27 23:03:17      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:计算过程   内存区域   类的方法   大内存   动态链接   函数   自动   tran   nat   

浅析Javajvm上的内存位置的分配

1.Java的内存区域简介

1>程序计数器:

一小块的内存空间,每个线程都有一个独立的计数器,线程私有;作用:作为当前线程代码行行号指示器,这个值可以选取下一条需要执行的字节码指令,例如分支,循环等,每创建一根线程会相应的产生一个程序计数器

2>栈

线程私有,用于存放局部变量,保存基本数据类型的值,操作数栈(保存着计算过程的中间结果),动态链接,方法入口和出口等信息;局部变量表中保存着函数的参数和局部变量,当调用结束以后,栈帧销毁,局部变量表也随之销毁 ,局部变量表可以复用过期的局部变量的槽位,栈帧弹栈有两种情况,return和异常,栈为先进后出的结构,有深度所以会溢出,上述所说的操作数栈和局部变量表是都是栈帧的组成部分,栈帧至少有三部分组成,操作数栈,局部变量表,帧数据区。

3>堆

线程共享;虚拟机所管理内存区域最大的一块地方,存放对象实例和数组,注意创建出来的对象只包含属于各自的成员变量(对象的属性),并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。

4>本方法地栈

为native服务(c/c++/fortran编写),行为和栈基本类似

5>方法区

线程共享,用于存放虚拟机加载的类信息,方法区中有常量池存放着常量(字面量),静态变量等数据

6>运行时常量池

方法区的一部分,用于存放编译期生成的各种字面量和符号引用(符号引用:类和接口的全限定名,字段的名称和描述符,方法的名称和描述符)

7>直接内存

直接内存不是java规范中的内存,也不隶属于堆,大小不受堆大小的限制,直接内存是指向java堆外,直接向系统申请内存空间,通常情况下直接内存的效率会优于java堆,直接内存和java堆的总和依然受限于操作系统能给出的最大内存限制。在nio(见后续nio)中是通过堆中的DirectByteBuffer实现对直接内存进行访问,能在一些场景中显著的提高性能

 

2.实例1:

package StaticTest;

public class Test {  //加载在方法区

        public static int i0=10;  //方法区

        public  final  int  i=100;//常量池

        public static void main(String[] args) {

                 int i1=10;  //栈

                 int i2=10;//栈

                 String str1="abc"; //栈指向常量池

                 String str2="abc"; //str2栈指向常量池

                 String str3=str1+str2;//栈指向堆

                 String str4="abcabc";栈指向常量池

                 String str5=new String("abc"); 栈指向堆

                 int  i3=i1+i2; 栈

                 int  i4=20; 栈

                 System.out.println(i0==i1);

                 System.out.println(i1==i2);

                 System.out.println(i3==i4);

                 System.out.println(str1==str2);

                 System.out.println(str3==str4);

                 System.out.println(str1==str5);

        }

}true    true   true    true    false    false

分析:首先会将类加载到方法区,然后放置一个class对象在堆区作为引用,main方法自身在方法区, i0在方法区等,基本数据类型i1,i2,以及与使用了常量池技术的字符串str1,str2,str4的引用在栈中,栈中的数据是可以共享的,所以i1,i2是指向同一个数字,对于栈中存放的基本类型数据,假如不存在那么就创建,假如存在那么就指向存在的地址,基本类型数据的运算也是在栈中进行(操作数栈),对于包装类(不论有没有new)与基本类型数据的==及各种运算,java会自动进行拆箱操作转换为相应的基本类型数据,指向相应的栈中,包装类(不论有没有new)与包装类(不论有没有new)的各种运算也会相应的转换为基本类型数据后进行相应的运算(==除外),new的实例在堆中,new只是创建各自的成员变量(不包含静态部分),不包含方法体,被final修饰的数据在常量池中,对于String和包装类都实现了常量池技术,String会先检查常量池中是否存在,假如不存在那么会创建,存在就指向存在的地址,String的加法是在堆中进行的,字符串的+底层是基于StringBuilder(见后续的java的字符处理)。在jdk6.0中String的常量池在方法区中,在jdk7.0中的String的常量池在堆中,综上所诉:new之后会创建各自的成员变量;而对于方法区中(这些是通过放入堆中的class对象来实现调用的)的静态成员变量及方法自身只会存在一份,对于常量池中的常量也只存在一份,且设定初始值后不能改变,对于Byte及小于-128~127之间的Integer以及Character的包装类以及String在没有new的前提下是直接指向常量池的同一个地址,new过之后会相应的进入堆中,对于其他的包装类,会相应的进入到堆中。常量池中的字面量和栈中的基本类型数据有区别,栈中的基本类型数据会相应的自动转换,常量池中的字面量不会自动转换,例如Double  d1=123456d;后续要加d,不加d就会编译错误等

技术分享图片

 

实例和对象的区别 :new或者反射出来的实例(newInstance等)叫实例,new出来或者反射出来的实例的引用叫对象;

 

浅析Java的jvm上的内存位置的分配

标签:计算过程   内存区域   类的方法   大内存   动态链接   函数   自动   tran   nat   

原文地址:https://www.cnblogs.com/gg128/p/9236387.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!