A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© lee123 中级黑马   /  2015-1-14 17:28  /  1175 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Java程序内存分配问题
想进入黑马最近在看毕向东老师的java视频,之前看过马士兵老师的java视频,讲的也不错但没有毕老师讲的通俗易懂。
两个老师在讲内存分配时有些不一致,具体是静态变量的内存分配。
下面是我对java程序在内存中分配过程的简介。可能有不对的地方,希望大家指出错误,给出正确的解释。
        先介绍5张图,1UNIX环境高级编程(第二版)第七章 7.6节截图
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
1 C程序的存储空间布局
正文:CPU执行的机器指令部分
初始化的数据:通常称为数据段,包含了程序中明确赋值的变量
未初始化的数据:通常称为bss段(blockstarted by symbol:符号开始块)在程序执行前,内核将此段中的数据初始化为0或空指针。

栈:自动变量以及每次函数调用时所需保存的信息都存放在此段
堆:通常在堆中进行动态分配存储空间。
图2是操作系统概念(第九版)第二部分第三章进程截图。
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
2 内存中的进程
         Code:文本段 程序代码。
         Data:数据段 全局变量
         Heap:堆区 程序运行期间动态的分配内存。
         Stack:栈区 临时数据

图3是马士兵老师的java视频截图
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg
3 马士兵java 内存分配图
         马老师的观点是:
         Codesegment:代码区存放代码
         Datasegment:数据区存放静态变量和字符串常量
         Stack:栈区 存放局部变量
         Heap:堆区 存放new出来的东西。
         4
根据毕老师
java
视频讲解画出的内存分配图
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg
4 毕老师java内存分配图
         5是本人根据图2结合图3改变而来的。
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg
5 改动后的内存分配图
本文以图5为主讲述java程序在内存中的分配
1 代码区:加载要执行的程序代码
2 数据区:存放程序中用static关键字修饰的静态变量和字符串常量
3 堆区:new出来的东西
4 栈区:保存临时数据和函数入栈时所需保存的信息
TestPerson.java为例讲解内存具体分配情况
TestPerson.java
class Person
{
       Stringname ;
       private static String city = "中国";
      intage ;
      publicPerson(String name,int age)
      {
//super(); == Object();
               this.name = name ;
               this.age= age ;
        }
        public String talk()
        {
                 return "我是 "+this.name+",今年 "+this.age+"岁,来自 "+city;
        }
}
public class TestPerson
{
         publicstatic void main(String[] args)
        {
                 Person p1 = new Person("张三",22);
                 System.out.println(p1.talk()) ;
        }
}

file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg
6 函数加载过程
         程序执行过程说明,如图
6
1先加载主函数main( ),将其调用信息入栈,序号1。
       2定义一个对象引用变量p1(栈中分配),2
3在new出对象前先加载对应构造函数Person(String name, int age),将其调用信息入栈,序号3。
4执行Person构造函数时,先调用超类Object默认的无参构造函数Object( ),将其调用信息入栈,序号4。
5构造函数Object()执行完毕后,它的栈空间被弹出,接着继续执行构造函数Person自己的函数体,如图7。
6在new对象时,随着类的加载,静态变量 city 优先在数据块中分配存储空间。如图7序号5。
7在new对象时,将字符串实参"张三"分配到数据区(图7序号6所示),并赋值给构造函数Person的形参neme(栈中分配空间),即name = "张三"如图中黄色虚线。而形参name 又赋值给类Person的成员变量name,即this.name = name如图7中红色虚线,所以成员变量name也指向数据区的"张三",即this.name = "张三"如图7中红色实线。
8将实参变量22赋值给构造函数的形参age(栈中分配),即age= 22,如图7中红色方框所示,形参age又赋值给类Person的成员变量age,即this.age = age = 22,如图中绿色虚线所示。
9构造函数执行完毕后,它的函数体内的临时变量消失,函数栈空间被弹出,只剩下引用变量P1指向堆中new出的对象,如图8所示。接着继续执行主函数中的System.out.println()函数。如图9所示
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg
7对象new出对象的过程
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg
8 对象 new出后的情况
10执行System.out.println(p1.talk())函数时把println()函数入栈(图9中绿色虚线框),println调用了对象p1的talk( )函数,所以把talk( )加载到栈顶,如图9中红色虚线框所示。
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg
9
11当talk( )函数执行完毕后,它的栈块被弹出,接着执行println( )函数,如图10所示。
12当println( )函数执行完毕后,它的栈块被弹出,接着执行main()函数,如图10所示
       13此时main函数也执行完毕,它的栈块被弹出。引用变量p1消失,如图10所示。
14整个程序执行完毕后,由java虚拟机的垃圾回收站负责回收堆中的空间。
15栈中的空间是自动释放。
16数据区中的静态变量city和字符串常量“张三”不知道由谁释放???
file:///C:/Users/lee/AppData/Local/Temp/msohtmlclip1/01/clip_image020.jpg
图10

通过看两位老师的视频和参考HeadFist Java等书籍,对java程序在内存中的分配做出了自己的理解,总感觉某些地方理解的有误,甚至有些地方的描述可能有点牵强附会,请大家给予宝贵的指导,本人万分感谢。

更多图片 小图 大图
组图打开中,请稍候......

评分

参与人数 1技术分 +4 收起 理由
lwj123 + 4 很给力!

查看全部评分

1 个回复

倒序浏览
谢谢鼓励,由于原文不能显示图片,我把图片放在当附件上传上去了,附件图片顺序就是原文中的顺序。自己在做总结时,感觉某些地方描述的不太恰当或者表达的有误,所以请大家指出错误,共同进步
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马