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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© mimawo 中级黑马   /  2016-5-2 20:41  /  407 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一、JAVA内存管理与GC机制
Java在JVM所虚拟出的内存环境中运行,java内存分为栈(stack)和堆(heap)两部分。


在Java中,JVM中的栈记录了线程的方法调用。每个线程拥有一个栈,线程创建时创建栈。在某个线程的运行过程中,如果有新的方法调用,那么该线程对应的栈就会增加一个存储单元,即帧(frame)。在frame中,保存有该方法调用的参数、局部变量、临时数据和返回地址。

栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中。 栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。 当被调用方法运行结束时,该方法对应的帧将被删除,参数和局部变量所占据的空间也随之释放。线程回到原方法,继续执行。当所有的栈都清空时,程序也随之运行结束。


2.
Java的普通对象存活在堆中。与栈不同,堆的空间不会随着方法调用结束而清空。因此,在某个方法中创建的对象,可以在方法调用结束之后,继续存在于堆中。这带来的一个问题是,如果我们不断的创建新的对象,内存空间将最终消耗殆尽,JVM启动时创建堆。

存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令) jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身


3.方法区
方法区是系统分配的一个内存逻辑区域,是用来存储类型信息的(类型信息可理解为类的描述信息)

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


4.运行时数据区过程

AppMain.javapublic   class  AppMain                //运行时, JVM把AppMain的信息都放入方法区{    public   static   void  main(String[] args)  //main 方法本身放入方法区。    {        //test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面        Sample test1 = new  Sample( " 测试1 " );        test1.printName();    }}Sample.javapublic   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()方法的字节码,开始执行它的指令。
执行main()方法第一条指令:
Sample test1=new Sample(“测试1”);
JVM执行该任务过程:

JVM在方法区查找Sample类信息,若没有Sample信息,则装载Sample类,然后把Sample类型信息放在方法区里。 创建实例:首先在堆区为新的实例分配内存,这个Sample实例持有者指向方法区Sample类型信息的引用。这里所说的引用,实际上指的是Sample类的类型信息在方法区中的内存地址。而这个地址呢,就存放了在Sample实例的数据区里。 位 于“=”前的test1是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,它被会添加到了执行main()方法的主线程的JAVA方法调用栈中。而“=”将把这个test1变量指向堆区中的Sample实例,也就是说,它持有指向Sample实例的引用。


5.在Java语言里堆(heap)和栈(stack)里的区别

栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第6点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马