Java中,有六个不同的地方可以存储数据:

1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(publicstatic final)。
6. 非RAM存储:硬盘等永久存储空间

这里我们主要关心栈、堆,对于 栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定
,具有很大的灵活性。
对于字符串:其对象的引用都是存储在栈中的,如果是 编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中 。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。

newString("China");
对于通过new产生一个字符串 (假设为”china”)时,会先去常量池中查找是否已经有了”china”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”china”对象的拷贝对象。这也就是有道面试题:Strings = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。

局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。(形式参数是局部变量)
成员变量存储在堆中的对象里面,由垃圾回收器负责回收

Java内存分配中的栈 :在函数中定义的一些基本类型的变量数据和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java在栈中为这个变量分配内存空间,当该变量退出其作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a =3;   int b = 3;  编译器先处理int a =
3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b =
3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响
到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b,
它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

Java内存分配中的堆 :堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。引用变量就相当于是为数组或者对象起的一个名称。
引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new
产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放
数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是 Java
比较占内存的原因
堆的优势是可以动态地分配内存 大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针!

原文地址:http://blog.csdn.net/zhangjinru123/article/details/51984313

JAVA中堆栈和内存分配详解(摘抄)的更多相关文章

  1. java程序运行时内存分配详解

    java程序运行时内存分配详解 这篇文章主要介绍了java程序运行时内存分配详解 ,需要的朋友可以参考下   一. 基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个 ...

  2. [Java]Java类和对象内存分配详解

    描述 代码说明: 一.当Person p1 = new Person();第一次被调用时需要做两件事: 1.先判断类加载器是否加载过Person类,如果没有则加载到Person类型到方法区 2.在堆中 ...

  3. JAVA中堆栈和内存分配原理

    1.栈.堆 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量 ...

  4. JAVA中堆栈和内存分配

    (一).栈.堆 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或 ...

  5. java程序运行时内存分配详解 (转)

    转自:http://www.tuicool.com/articles/uU77v2 一.  基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个或者多个线程,每一个Ja ...

  6. Java学习之二维数组定义与内存分配详解

    二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的元素有多少个. 注意: ...

  7. Java 中的异常和处理详解

    Java 中的异常和处理详解 原文出处: 代码钢琴家 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误 ...

  8. Java 中数组的内存分配

    Java 中数组的内存分配 1.Java 程序在运行时,需要在内存中分配空间.为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据和内存管理方式. 2.数组基本概念 数组是 ...

  9. 内存分配详解 malloc, new, HeapAlloc, VirtualAlloc,GlobalAlloc

    很多地方都会使用内存,内存使用过程中操作不当就容易崩溃,无法运行程序,上网Google学习一下,了解整理下他们之间的区别以及使用 ,获益匪浅 0x01 各自的定义和理解 (1)先看GlobalAllo ...

随机推荐

  1. 如何在Kubernetes里给PostgreSQL创建secret

    创建一个initdb.sql文件,输入如下内容: -- This is a postgres initialization script for the postgres container. -- ...

  2. [转]Ubuntu 配置 Android 开发 环境

    转自:http://blog.csdn.net/shulianghan/article/details/20855541 1. 安装 Android Studio (1) 下载Android Stud ...

  3. Android(java)学习笔记53:局部内部类

    1. 局部内部类 /* 局部内部类 A:可以直接访问外部类的成员 B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能 面试题: 局部内部类访问局部变量的注意事项? A:局 ...

  4. luogu P2424 约数和

    嘟嘟嘟 求出[L, R]中每一个数的约数再相加必定会超时,所以换一种思路:枚举约数d. 对于一个约数d,能整除他的数可以写成k * d, (1 <= k <= ⌊n / d⌋),因此约数d ...

  5. 使用maven创建项目

    http://192.168.4.112/rdmanager/main/index.jhtml 1.对于第一次下载某个项目的源码,按照下面的步骤进行: (1)在D:\projects\目录下的空白位置 ...

  6. o'Reill的SVG精髓(第二版)学习笔记——第十章

    10.1 裁剪路径 创建SVG文档时,可以通过制定感兴趣区域的宽度和高度建立视口.这会变成默认的裁剪区域,任何绘制在该范围外部的部分都不会显示.你也可以使用<clipPath>元素来建立自 ...

  7. 标准对象——RegExp

    字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求无处不在.比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样麻烦且代码难以复 ...

  8. Ajax全接触(1)

    Ajax全称:Asynchronous JavaScript and XML(异步的JavaScript和XML) .Ajax不是某种编程语言 是一种在无需重新加载整个网页的情况之下能够更新部分网页的 ...

  9. java交换两个值的三种方法 经典

    1.中间变量(在开发中常用) int c=a; a=b; b=c; System.out.println("a的值: "+a+" b的值: "+b); 2.按位 ...

  10. SpringBoot非官方教程 | 第二十六篇: sprinboot整合elk,搭建实时日志平台

    转载请标明出处: 原文首发于https://www.fangzhipeng.com/springboot/2017/07/11/sprinboot25-elk/ 本文出自方志朋的博客 这篇文章主要介绍 ...