`
hududumo
  • 浏览: 237750 次
文章分类
社区版块
存档分类
最新评论

java中数据在内存中的存储详解

 
阅读更多
<wbr>1. <p style="margin:2px; padding-top:0px; padding-bottom:0px; float:left"><wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> 有这样一种说法,如今争锋于IT战场的两大势力,MS一族偏重于底层实现,Java一族偏重于系统架构。说法根据无从考证,但从两大势力各自的社区力量和图书市场已有佳作不难看出,此说法不虚,但掌握Java的底层实现对Java程序员来说是至关重要的,本文介绍了Java中的数据在内存中的存储。<br>   <br>   <span style="color:rgb(255,0,0)">2 内存中的堆(stack)与栈(heap)<br></span>  <span style="color:rgb(255,0,255)">Java程序运行时有6个地方可以存储数据,它们分别是<span style="color:rgb(0,0,255)">寄存器、栈、堆、静态存储、常量存储和非RAM存储</span>,主要是堆与栈的存储。</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(255,0,255)"><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></span><span style="color:rgb(204,0,255)">【随机存储器 :Random Access Memory 】</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <br>   <span style="color:rgb(0,0,255)">栈与堆都是Java用来在RAM中存放数据的地方</span>。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。<span style="color:rgb(0,0,255)">栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器</span>。另外,<span style="color:rgb(0,0,255)">栈数据可以共享</span>。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。<span style="color:rgb(0,0,255)">堆的优势是可以动态地分配内存大小</span>,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但<span style="color:rgb(0,0,255)">缺点是,由于要在运行时动态分配内存,存取速度较慢</span>。</p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <br>   <span style="color:rgb(204,0,204)">【 寄存器位于CPU中 】</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(204,0,204)"><br></span>  3 Java中数据在内存中的存储<br>   <span style="color:rgb(255,0,0)">3.1基本数据类型的存储<br></span>  <span style="color:rgb(0,0,255)">Java的基本数据类型共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。</span><span style="color:rgb(255,0,255)">这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。<span style="color:rgb(255,0,0)">值得注意的是:</span>自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在</span>。<span style="color:rgb(0,0,255)">如int a = 3;<span style="color:rgb(255,0,255)">这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知</span>(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中</span>。</p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <br>   <span style="color:rgb(0,0,255)">另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享</span>。</p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr><wbr><wbr>假设我们同时定义:<br>   int a = 3;</wbr></wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr><wbr><wbr>int b=3;<br>   编译器先处理int a = 3;<span style="color:rgb(0,0,255)">首先它会在栈中创建一个变量为a的引用</span>,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b这个引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。</wbr></wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(255,0,255)"><wbr><wbr></wbr></wbr></span><span style="color:rgb(153,0,255)">【上文提到了"引用+数值+内存地址"这三个名词,其中变量名就是引用,给变量赋的值就是数值,</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(153,0,255)"><wbr></wbr></span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(153,0,255)"><wbr><wbr><wbr><wbr>而所提到的内存是抽象的内容,让引用指向的不是数值,而是存取数值的那块内存地址】</wbr></wbr></wbr></wbr></span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px">   定义完a与b的值后,再令a = 4;那么,b不会等于4,还是等于3。在编译器内部,遇到时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。</p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr><wbr><wbr><span style="color:rgb(153,0,255)">【定义变量,给变量赋值,然后在编译的过程中就可以将其保存在内存中了】</span></wbr></wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr><br>   <span style="color:rgb(255,0,0)">3.2对象的内存模型<br></span>  <span style="color:rgb(255,0,255)">在Java中,创建一个对象包括对象的声明和实例化两步</span>,下面用一个例题来说明对象的内存模型。<br>   假设有类Rectangle定义如下:</wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr><wbr><wbr>【<span class="word"><strong>Rectangle:矩形</strong></span>】<br>   class Rectangle{<br>   double width,height;<br>   Rectangle(double w,double h){<br>   width=w;height=h; }}<br>   <span style="color:rgb(255,0,255)">(1)声明对象时的内存模型<br></span>  <span style="color:rgb(0,0,255)">用Rectangle rect;声明一个对象rect时,将在栈内存为对象的引用变量rect分配内存空间,但Rectangle的值为空,称rect是一个空对象。空对象不能使用,因为它还没有引用任何“实体”。<br></span>  <span style="color:rgb(255,0,255)">(2)对象实例化时的内存模型<br></span>  <span style="color:rgb(255,0,0)">当执行rect=new Rectangle(3,5);时,会做两件事</span>:<br>   <span style="color:rgb(0,0,255)">在堆内存中为类的成员变量width,height分配内存,并将其初始化为各数据类型的默认值;接着进行显式初始化(类定义时的初始化值);<span style="color:rgb(255,0,255)">最后调用构造方法,为成员变量赋值。</span><br>   返回堆内存中对象的引用(相当于首地址)给引用变量rect,以后就可以通过rect来引用堆内存中的对象了。</span></wbr></wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(0,0,255)"><wbr><wbr><wbr></wbr></wbr></wbr></span><span style="color:rgb(102,255,0)">(他奶奶的,不是很理解这两句话!)</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(0,0,255)"><br></span>  (3)创建多个不同的对象实例<br>   一个类通过使用new运算符可以创建多个不同的对象实例,这些对象实例将在堆中被分配不同的内存空间,改变其中一个对象的状态不会影响其他对象的状态。例如:<br>   Rectangle r1=new Rectangle(3,5);<br>   Rectangle r2=new Rectangle(4,6);<br>   此时,将在堆内存中分别为两个对象的成员变量width、height分配内存空间,两个对象在堆内存中占据的空间是互不相同的。如果有<br>   Rectangle r1=new Rectangle(3,5);<br>   Rectangle r2=r1;<br>   则在堆内存中只创建了一个对象实例,在栈内存中创建了两个对象引用,两个对象引用同时指向一个对象实例。<br>   <span style="color:rgb(255,0,0)">3.3包装类数据的存储<br></span>  <span style="color:#0000ff"><span style="color:rgb(255,0,255)">基本型别都有对应的包装类</span>:如int对应Integer类,double对应Double类等,<span style="color:rgb(255,0,255)">基本类型的定义都是直接在栈中</span>,如果用包装类来创建对象,就和普通对象一样了。例如:<span style="color:rgb(255,0,255)">int i=0;i直接存储在栈中</span>。<wbr><span style="color:rgb(153,0,255)">Integer<wbr><span style="color:rgb(102,255,0)"><span style="color:rgb(153,0,255)">i</span><span style="color:rgb(255,0,0)">(i此时是对象)</span></span>= new Integer(5);这样,<span style="color:rgb(255,0,0)">i对象</span>数据存储在堆中,i的引用存储在栈中,通过栈中的引用来操作对象。</wbr></span></wbr></span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(153,0,255)"><wbr><wbr><wbr></wbr></wbr></wbr></span><span style="color:rgb(255,0,255); font-size:20px">【数据存储在堆中,引用存储在栈中】</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <span style="color:rgb(0,0,255)"><br></span>  <span style="color:rgb(255,0,0)">3.4 String 类型数据的存储<br></span>  <span style="color:rgb(255,0,255)">String是一个特殊的包装类数据。</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> 可以用<wbr><wbr><wbr><wbr><wbr>String str = new String("abc");的形式来创建;</wbr></wbr></wbr></wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> 也可以用<wbr><wbr><wbr>String str = "abc";的形式来创建。</wbr></wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <wbr></wbr></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> 第一种创建方式,和普通对象的的创建过程一样;</p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> 第二种创建方式,Java内部将此语句转化为以下几个步骤:<br>   (<span style="color:rgb(0,0,255)">1)先定义一个名为str的对String类的对象引用变量:String str;<br>   (2)在栈中查找有没有存放值为“abc”的地址,<span style="color:rgb(255,0,255)">如果没有</span>,则<span style="color:rgb(255,0,255)">开辟一个存放字面值为“abc”的地址</span>,接着<span style="color:rgb(255,0,255)">创建一个新的String类的对象o</span>,并<span style="color:rgb(255,0,255)">将o的字符串值指向这个地址</span>,而且<span style="color:rgb(255,0,255)">在栈中这个地址旁边记下这个引用的对象o</span>。如果已经有了值为“abc”的地址,则查找对象o,并返回o的地址。<br>   (3)<span style="color:rgb(255,0,255)">将str指向对象o的地址</span>。</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <br>   值得注意的是,一般String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用。<br>   为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。<br>   String str1=“abc”;<br>   String str2=“abc”;<br>   System.out.println(s1==s2);//true<br>   注意,这里并不用str1.equals(str2);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,str1与str2是否都指向了同一个对象。<br>   我们再接着看以下的代码。<br>   Stringstr1=new String(“abc”);<br>   Stringstr2=“abc”;<br>   System.out.println(str1==str2);//false<br>   创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。<br>   以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。<br>   3.5数组的内存分配<br>   当定义一个数组,int x[];或int []x;时,在栈内存中创建一个数组引用,通过该引用(即数组名)来引用数组。x=new int[3];将在堆内存中分配3个保存int型数据的空间,堆内存的首地址放到栈内存中,每个数组元素被初始化为0。<br>   <br>   <span style="color:rgb(255,0,0)">4 内存空间的释放<br></span>  <span style="color:rgb(0,0,255)">栈上变量的生存时间受限于当前函数的生存时间,函数退出了,变量就不存在了。</span><span style="color:rgb(204,0,255)">在堆中分配的对象实例,当不再有任何一个引用变量指向它时,这个对象就可以被垃圾回收机制回收了。<br></span>  <br>   <span style="color:rgb(255,0,0)">5 总结堆栈</span></p> <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px">   <span style="color:rgb(0,0,255)">再来看Java的内存,栈内存用来存放一些基本类型的变量和数组及对象的引用变量,</span><span style="color:rgb(255,0,255)">而堆内存主要是来放置对象实例的</span>。明白这个就能很好的解释多态、继承、覆盖方面的问题了</p> </wbr>
分享到:
评论

相关推荐

    java堆栈的区别 -- 详解

    另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活 2.5堆和栈中的存储内容 栈: 在函数调用时,...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    125集专攻JAVA基础 JAVA零基础入门学习视频教程 动力节点JAVA视频教程.txt

    北京动力节点-Java编程零基础教程-119-Java基本语法-方法详解-方法的调用过程-方法调用过程中栈内存的变化.avi 北京动力节点-Java编程零基础教程-120-Java基本语法-方法的重载-什么是方法重载.avi 北京动力节点-...

    Java数组详解(Java基础)

    变量:内存中的一块存储空间, 存储的就是常量。 特点:一个变量只能存储一个数据,不能存储多个。 需求:统计把一个班级的所有学生30个人java成绩? 解决1:使用变量存储,需要声明30个变量: int java1=90; int java...

    JVM 运行时数据区域,垃圾回收机制,类加载机制三大功能详解.docx

    运行时数据区域: 在运行时数据区里存储类Class文件元数据(方法区),对象和数组(堆),方法参数局部变量(栈)等。 垃圾回收机制: java 语言的优势之一就是它的自动内存管理,主要回收运行时数据区域的堆内存里的数据 ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    免费分享 Java面试笔记 面试八股文 计算机网络基础

    JVM(Java虚拟机):Java内存管理详解、垃圾回收机制、垃圾回收器等;MySQL:基础知识、存储引擎、日志、SQL优化、数据索引、锁、事务、高可用实现等;Spring:IOC、AOP、声明式事务、MVC等;Redis:持久化过程、高...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     8.1 Java对象在JVM中的生命周期  8.2 理解Session的缓存  8.2.1 Session的缓存的作用  8.2.2 脏检查及清理缓存的机制  8.3 Java对象在Hibernate持久化层的状态  8.3.1 临时对象的特征  8.3.2 持久化对象的...

    疯狂JAVA讲义

    6.9.1 对象在内存中的状态 226 6.9.2 强制垃圾回收 227 6.9.3 finalize方法 228 6.9.4 对象的软、弱和虚引用 230 6.10 修饰符的适用范围 233 6.11 使用JAR文件 234 6.11.1 jar命令详解 235 6.11.2 创建可执行...

    Android典型技术模块开发详解

    10.6.3 使用ContentResolver操作ContentProvider中的数据 10.7 本章小结 第11章 网络通信 11.1 TCP协议 11.1.1 服务端的创建 11.1.2 客户端创建 11.2 UDP协议 11.2.1 服务端的创建 11.2.2 客户端创建 11.3 ...

    [Java] volatile 详详解!

    前言: 要真正搞懂volatile的特性需要与JMM对比来看 JMM(线程安全的保证) JMM:JAVA内存模型(java memory model) 是一种抽象概念,并不真实存在,它描述的是一组规则...JMM中规定所有变量都存储在主内存,主内存是

    java删除指定字符串leetcode-Data-Structures-Algorithms:此存储库的唯一目的是提醒某些数据结构和算法如何在

    该存储库的唯一目的是提醒某些数据结构和算法如何在一页中工作。 大批 数组详解数组的属性 数组可以存储指定数据类型的数据 它具有连续的内存位置 数组的每个“单元格”都有唯一的索引 索引从 0 而不是 1 开始 数组...

    java8集合源码-inMemoryKeyValue:Java集合直到内存和性能的最后一个面包屑

    微秒的存储键值的中位延迟? 如何从键值存储中获得小于 1 微秒的中位延迟? 科洛博克 Java () 中围绕集合的一系列项目。 Koloboke 集合 API 精心设计的 Java Collections Framework 扩展,具有原始专业化等功能。 ...

    Android开发应用实战详解源代码

    6.8 内存和存储卡 6.9 实现定时闹钟 6.10 黑名单 6.11 桌面背景图片轮换 6.12 监听发送短信状态 6.13 修改默认开机显示 6.14 小结 第7章 娱乐和多媒体应用 7.1 获取图片的宽和高 7.1.1 实现原理 7.1.2 位图操作的...

    JAVA核心知识点整理(有效)

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【Redis】redis五种常见的数据类型详解 123 String字符串类型 124 List列表类型 126 Set集合类型 128 Hash散列类型 130 Redis的有序集合ZSet数据类型 131 【Redis】Redis的存储结构,或者说如何工作的,与mysql的...

    详解MongoDB4.0构建分布式分片群集

    分片技术可以满足 MongoDB 数据量大量增长的需求,当一台 MongoDB 服务器不足以存储海量数据或不足以提供可接受的读写吞吐量时,我们就可以通过在多台服务器上分割数据,使得数据库系统能存储和处理更多的数据。...

Global site tag (gtag.js) - Google Analytics