jvm内存

Runtime Data Area 运行时数据区就是我们常说的jvm内存

 

 

1.程序计数器

类似汇编语言中的cs:ip,指向下条指令地址。多线程中每个线程都有自己的程序计数器

 

2.java栈

java栈也称作虚拟机栈,事实上java栈是java方法执行的内存模型。

java栈中存放许多栈帧,每个栈帧对应一个被调用的方法。当线程执行一个方法就会创建一个对应的栈帧,并将之压栈,方法执行完之后将

栈帧出栈。当然每个线程都有对应的虚拟机栈。

栈帧中包含局部变量表、操作数栈、指向当前方法所属类的运行时常量池的引用、方法返回地址和一些额外信息。

 

①局部变量表(local variables):用于存储方法中的局部变量(包括在方法中声明的非静态变量以及函数形参)。对于基本数据类型变量,直接存储值,而引用类型的变量,则存的是指向对象的引用。

局部变量表所需的内存空间在编译期间完成分配,大小是确定的其中64位的long和double占两个局部变量空间,其余占一个。在方法运行期间表大小了两种异常:如果线程请求的栈深度大于虚拟机允许的深度,将抛出StackOverflowError异常;如果虚拟机可以动态扩展,当扩展时无法申请足够内存会抛出OutOfMemoryError异常

 

②操作数栈(operand stack):“详情了解栈的应用之表达式求解”

 

③运行时常量池的引用(reference to runtim是不会改变的。

java虚拟机规范,对这个区域规定e constant pool):方法执行中可能要用到类中的常量,需要一个引用指向他们

 

④方法返回地址(return address):一个方法执行之后,要返回之前调用它的地方,就是这个返回地址

 

3.本地方法栈

与java栈的作用和原理非常相似。本地方法栈是为执行本地方法服务的。

 

4.堆heap

堆是所有线程共享的一块内存区域,在虚拟机启动时创建。所有的对象实例和数组都要在堆上分配内存,这也是它的唯一目的。

堆可以只要逻辑上连续就行。如果在堆中没有内存完成实例分配,并且堆也无法扩展时,将会抛出OutOfMemoryError异常。

 

5.方法区

方法区又叫静态区,跟堆一样,被所有线程共享。方法区中包含的是整个程序中永远唯一的元素,如class,static变量

 

 

 

 

现给出例子以更直观了解:

 

public   class  AppMain                //运行时, jvm 把appmain的信息都放入方法区
{

public   static   void  main(String[] args)  //main 方法本身放入方法区。
{

Sample test1 = new  Sample( " 测试1 " );   //test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面

Sample test2 = new  Sample( " 测试2 " );

test1.printName();

test2.printName();

}
}



 public   class  Sample        //运行时, jvm 把appmain的信息都放入方法区
{

private  name;      //new Sample实例后, name 引用放入栈区里,  name 对象放入堆里

public  Sample(String name)
{
this .name = name;
}

public   void  printName()   //print方法本身放入 方法区里。
{
System.out.println(name);
}
}

 

系统启动java虚拟机进程后,首先从classpath中找到AppMain.class文件,读取这个文件中的二进制数据,然后把AppMain类的类信息存放到运行时数据区的方法区中。即AppMain类的加载。

 

接着,java虚拟机定位到方法区中AppMain类的Main()方法的字节码,开始执行它的指令。第一句:

Sample test1 = new Sample("测试1");

1.虚拟机建一个Sample实例,到方法区找Sample类的类型信息。没有,加载Sample类。

2.在堆中为Sample实例分配内存,这个Sample实例持有指向方法区中Sample类的类型信息的引用。这个引用实际上就是Sample类类型信息在方法区中的内存地址。

3.test1就是在方法栈中的的一个变量。“=”将这个test1变量指向堆区中的Sample实例。

 

接下来,虚拟机执行test1.printName()方法时,根据局部变量test1持有的引用,定位到堆中的Sample实例,再根据Sample实例持有的引用,定位到方法区中Sample类的类型信息,从而获得printName()方法的字节码,执行printName()方法包含的指令。

 

 

参考文档:http://blog.sina.com.cn/s/blog_45873fe10101qh3v.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值