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

浅析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出来或者反射出来的实例的引用叫对象;

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

时间: 2024-11-03 17:13:58

浅析Java的jvm上的内存位置的分配的相关文章

Java获得jvm占用的内存和系统的可用内存信息

1 import java.text.DecimalFormat; 2 3 public class Main { 4 /** 5 * 显示JVM总内存,JVM最大内存和总空闲内存 6 */ 7 public void displayAvailableMemory() { 8 DecimalFormat df = new DecimalFormat(“0.00″) ; 9 10 //显示JVM总内存 11 long totalMem = Runtime.getRuntime().totalMem

new一个JAVA对象的时候,内存是怎么分配的?

new 对象的时候 在内存中 建立一个 内存区域 就是堆内存 用来存放对象的属性,当new完对象把对象的地址赋给对象的引用变量 这个时候 又在内存中建立一个区域 叫栈内存 用来存储 引用变量 引用变量存储对象的地址, 当对象没有被任何引用变量 引用的时候 就变成了 垃圾会被java的垃圾清除机制清除掉

java学习-----jvm的内存分配及运行机制

VM运行时数据区域: 根据<Java虚拟机规范(第二版)>的规定,JVM包括下列几个运行时区域: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的

java基础---JVM内存管理以及内存运行机制学习总结

自己从网上搜资料拼接了一张JVM内存图:如下图所示: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的 方式去实 现),字节码解释器工作时就是通过改

java中JVM的原理

一.Java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机. Java虚拟机总是开始于一个main()方法,这个方法必须是公有.返回void.直接受一个字符串数组.在程序执行时,你必须给Java虚拟机指明这个包换main()方法的类名. Main()方法是程序的起点,他被执行的线程初始化为程序的初始线程.程序中其他的线程都由他来

Java基础-JVM

jvm=> java虚拟机 一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机. Java虚拟机总是开始于一个main()方法,这个方法必须是公有.返回void.直接受一个字符串数组.在程序执行时,你必须给Java虚拟机指明这个包换main()方法的类名. Main()方法是程序的起点,他被执行的线程初始化为程序的初始线

java中JVM的原理【转】

一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机. Java虚拟机总是开始于一个main()方法,这个方法必须是公有.返回void.直接受一个字符串数组.在程序执行时,你必须给Java虚拟机指明这个包换main()方法的类名. Main()方法是程序的起点,他被执行的线程初始化为程序的初始线程.程序中其他的线程都由他来

【转载】Java的JVM原理

转自:http://blog.csdn.net/witsmakemen/article/details/28600127/ 一.Java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机. Java虚拟机总是开始于一个main()方法,这个方法必须是公有.返回void.直接受一个字符串数组.在程序执行时,你必须给Java虚拟机指明这

JAVA的JVM虚拟机工作原理.V.1.0.0

注意:一下内容纯属个人理解,如有错误,欢迎批评指正. (90度弯腰)谢谢. java在JVM上的运行过程: 1,编辑好的java代码(IDE无报错,测试运行无错误): 2,java源代码通过javac编译成class文件(字节码文件,全是二进制数据,是供神看的东西): 3,class文件加载到JVM上,继续二次编译(或者说上次的根本就不算编译,就是一格式转换),进行平台格式化(这也是java广告的来源): 4,格式化后的文件,就可以在相应的平台上进行运行了(机器直接读取格式化后的二进制文件,也就