现在的位置: 首页 > 综合 > 正文

java运行内存分配图

2013年09月16日 ⁄ 综合 ⁄ 共 2420字 ⁄ 字号 评论关闭
Java的内存分配
  Java程序运行时的内存结构分成:方法区、栈内存、堆内存、本地方法栈几种。
  
方法区
   存放装载的类数据信息,包括:基本信息:每个类的全限定名、每个类的直接超类的全限定名、该类是类还是接口、该类型的访问修饰符、直接超接口的全限定名的有序列表。每个已装载类的详细信息:运行时常量池、字段信息、方法信息、静态变量、到类classloader的引用、到类class的引用。
  栈内存
    Java栈内存由局部变量区、操作数栈、帧数据区组成,以帧的形式存放本地方法的调用状态(包括方法调用的参数、局部变量、中间结果……)。
  堆内存
    堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
  本地方法栈内存
    Java通过Java本地接口JNI(Java Native Interface)来调用其它语言编写的程序,在Java里面用native修饰符来描述一个方法是本地方法 
Java对象创建内存示意图


java中内存主要包含4块,即heap(堆内存)、stack(栈内存)、data segment(静态变量或是常量存放区)、codesegment(方法区). 
堆内存中存放的是new出的对象,new出的对象只包含成员变量。 
栈内存中:存放的是局部成员变量。对于基本的数据类型存放的是基本变量的值,而对于对象变量,存放的是堆内存的地址。 
静态、常量区:存放的是静态变量(类变量)或是常量。 
方法区:存放的是对象的方法。因此即使new出多个对象也是只是存在一个方法。 

如 
A a = new A(); A中含有一个work方法,2个成员变量a,b。那么对应的内存分配为 
则 a是分配在栈内存中。里面存放了一个指向堆内存中存放的new A()的地址。 
new A()会导致在堆内存中分配一块空间,该内存中的A对象同时会含有a和b。 
work()方法会在codesegment区中分配内存。 
如果此时 A b = a;则表示把a的值复制给b,即b的值为a中保存的地址

**************************************************************************************************************************
**************************************************************************************************************************


这是一篇关于Java内存结构组织的文章,涉及的概念主要有方法区Java栈java堆。通过这个文章,可以加深对Java对象的理解,以及优化代码的结构。

 

开始: 

想写这篇总结酝酿了有个来月了,却始终感觉还差点什么东西,一直未敢动笔。

 
     
最近两天连夜奋战,重新整理下前面查阅的资料、笔记,还是决定将它写出来。

 
     
现在提出几个问题,如果都能熟练回答的大虾,请您飘过.如以往一样,我是小菜,本文自然也是针对小菜阶层的总结。

 

首先是概念层面的几个问题:

 

  • Java中运行时内存结构有哪几种?
  • Java中为什么要设计堆栈分离?
  • Java多线程中是如何实现数据共享的?
  • Java反射的基础是什么?

然后是运用层面:

  • 引用类型变量和对象的区别?
  • 什么情况下用局部变量,什么情况下用成员变量?
  • 数组如何初始化?声明一个数组的过程中,如何分配内存?
  • 声明基本类型数组和声明引用类型的数组,初始化时,内存分配机制有什么区?
  • 在什么情况下,我们的方法设计为静态化,为什么?(上次胡老师问文奇,问的哑口无言,当时想回答,却老感觉表述不清楚,这里也简单说明一下)

好了,问题提完了,如果您都能一眼看出答案,那么,没有必要再浪费您宝贵的时间看下去了

如果您还不太明白,请跟随我一路走下去。

 

Java中运行时内存结构

   1.1 方法区: 

方法区是系统分配的一个内存逻辑区域,是JVM在装载类文件时,用于存储类型信息的(类的描述信息)。

    

方法区存放的信息包括:

            1.1.1类的基本信息:

  1. 每个类的全限定名
  2. 每个类的直接超类的全限定名(可约束类型转换)
  3. 该类是类还是接口
  4. 该类型的访问修饰符
  5. 直接超接口的全限定名的有序列表

             1.1.2已装载类的详细信息

  1.  运行时常量池

    在方法区中,每个类型都对应一个常量池,存放该类型所用到的所有常量,常量池中存储了诸如文字字符串、final变量值、类名和方法名常量。它们以数组形式通过索引被访问,是外部调用与类联系及类型对象化的桥梁。(存的可能是个普通的字符串,然后经过常量池解析,则变成指向某个类的引用)

  2.  字段信息

    字段信息存放类中声明的每一个字段的信息,包括字段的名、类型、修饰符。

    字段名称指的是类或接口的实例变量或类变量,字段的描述符是一个指示字段的类型的字符串,如private A a=null;a为字段名,A为描述符,private为修饰符

  3.  方法信息

    类中声明的每一个方法的信息,包括方法名、返回值类型、参数类型、修饰符、异常、方法的字节码。

    (在编译的时候,就已经将方法的局部变量、操作数栈大小等确定并存放在字节码中,在装载的时候,随着类一起装入方法区。)

    在运行时,JVM从常量池中获得符号引用,然后在运行时解析成引用项的实际地址,最后通过常量池中的全限定名、方法和字段描述符,把当前类或接口中的代码与其它类或接口中的代码联系起来。
  4.  静态变量

    这个没什么好说的,就是类变量,类的所有实例都共享,我们只需知道,在方法区有个静态区,静态区专门存放静态变量和静态块。

  5.  到类classloader的引用到该类的类装载器的引用。
  6.  到类class 的引用虚拟机为每一个被装载的类型创建一个class 实例,用来代表这个被装载的类。 

   由此我们可以知道反射的基础

抱歉!评论已关闭.