飞加Java学习笔记_内存管理(1)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
学习就要多问一些“为什么”和“怎么”,这样才有助于提高。这就是著名的5W2H 理论!
一、JAVA 内存管理机制概述
让我们先了解一下垃圾收集的工作原理。垃圾收集器的工作就是寻找那些不再被应用程序需要的对象,当它们不会再被访问或引用的时候清除它们。所以如果使用完变量后,最好将其马上置为null ,这样gc 才会认为它不会再被访问或引用。
本文将介绍Java 内存管理机制,并以int 变量和String 为例来,来讨论它们是如果使用内存的。
Java 内存分为栈(stack)与堆(heap),这两种都是由Java 自动来管理,程序员是不能通过编程来控制的。下面来介绍这两种内存:
堆(heap)内存:用于存放类的对象,如Data d1 = new Date(),d1是分配在堆内存中的,堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小。
栈(stack)内存:用于存放基本类型的变量,如int a = 5, a 是分配在栈内存中的,栈内存中的数据是可以共享。
二、JAVA 内存管理举例分析
1. Java 内存管理举例---int 变量
当在系统中声明一个int 变量时,系统做了哪些工作呢,如图1:
样例代码分析:
1. int a = 5; //新分配给5一段内存
2. int b = 6; //新分配给6一段内存
声明一个int 变量,如int age =20
将age 指向20,
不用再次分配内存分配一段内存给20,并将age 指向它
栈(stack)中有20这个值吗?
3. a = 7; //新分配给7一段内存, 存放5的那段内存将会被回收
第一行,在栈中创建一个a 的引用,然后在栈中搜索,看是否有3这个值,如果没有,就将3存在栈中,并且将a 指向3;
第二行,处理b ,如果在栈中有6这个值,那么直接让b 指向6,而不用再次分配内存;如果栈中没有6,那么需要在栈中再次开辟一段内存用于存储b 。
第三行,再处理a, 此时会在栈内存中重新检索,看有没有7这个值,如果有,那么将a 重新指向7;如果没有,则再开辟一段内存,然后将a 指向7。
2. Java 内存管理举例---String 对象
声明String 类的对象有两种方法,一种是new 一个对象,一种是直接将字符串赋给对象,下面将分别讨论两种方法的内存管理机制。
第一种方式:new ,如图2:
使用这种方式创建对象时,jvm 是不会主动把该对象放到strings pool 里面的,除非程序调用String 的intern 方法。
第二种方式:直接赋值,如图3:
样例代码分析:
1.String s1 = new String("Beijing");
2.Stirng s2 = "Beijing";
如String s1 = “飞加”;
则返回已有的String 对象给用
户,而不会在heap 中重新创建一
个新的String 对象jvm 则在堆(heap)中创建新的String 对象,将其引用返回给s1,同时将该引用添加至strings pool 中
在strings pool(由栈负责维护)中有“飞加”吗?
Yes(有)
No(无)如String s1 = new String(“飞加”);
JVM 直接在堆(heap)中分配一段内存给“飞加”,并将
s1指向它。而不会管在堆(heap)中是否已经有“飞加”
图2
图3
3.System.out.println("s1 == s2");
4.Stirng s3= "Beijing";
5.System.out.println("s2== s3");
第1行,jvm 在堆上创建一个String对象,并不放到栈里
第2行,jvm 在strings pool中找不到值为“Beijing”的字符串,因此在堆上创建一个String 对象,并将该对象的引用加入至strings pool中,此时堆上有两个String对象第3行,返回false,因为是两个不同的对象
第4行,此时,jvm发现strings pool中已有“Beijing”对象了,因为“Beijing”equels “Beijing”, 因此直接返回s2指向的对象给s3,也就是说s2和s3是指向同一个对象的引用第5行,返回true,因为是同一对象的引用。
希望通过上面的分析,同学们能懂得内存的分配是怎么回事。
三、关于String类的intern()方法
先看看简介吧:)
public String intern()返回字符串对象的规范化表示形式。
当调用intern 方法时,如果池已经包含一个等于此String 对象的字符串(该对象由equals(Object) 方法确定),则返回池中的字符串。否则,将此String 对象添加到池中,并且返回此String 对象的引用。
它遵循对于任何两个字符串s 和t,当且仅当s.equals(t) 为true 时,s.intern() == t.intern() 才为true。
返回:一个字符串,内容与此字符串相同,但它保证来自字符串池
如果觉得上面讲的太空的话,那么请看下面的代码分析。
1.String s1 = new String("Beijing");
2.s1 = s1.intern();
3.String s2 = "Beijing";
4.System.out.println(s1 == s2);
第1行,jvm 在堆上创建一个String对象
第2行,程序显式将s1放到strings pool中,intern运行过程是这样的:首先查看strings/pool 有没“Beijing”对象的引用,没有,则在堆中新建一个对象,然后将新对象已经
成为垃圾对象了,随时会被GC收集对象的引用加入至strings pool中。执行完该
语句后,s1原来指向的String
第3行,s1, s2共同指向”Beijing”
第4行,返回true
四、关于String类的非可变(immutable)性质
当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。如: