java的内存管理

资料:

(1)浅谈java垃圾回收机制:
https://www.cnblogs.com/mxlandxt/p/6972252.html

在java中,内存的管理可分为Stack、Heap、方法区PermGen(Data Segment、Code Segment)。

java的内存管理_第1张图片

程序变量表示的数据存储在哪里?

存储在虚拟内存中(进程的虚拟地址空间)。
程序中用到的所有地址,都不是真实的内存地址,而是虚拟内存地址。
操作系统和硬件会将虚拟内存映射成真实的内存。
当程序访问的虚拟内存页(虚拟内存是分成一页一页的,比如每页4K)不在真实内存中时,就会触发缺页中断,操作系统这时再将对应的页载入到真实内存中,再重新访问。
假如真实内存满了,就将太久没有使用的页转出到磁盘当中,程序就认为自己独立拥有了几个G的虚拟地址空间。
程序启动时,也不需要真的将信息载入到真实内存中,而只需要建立映射。这样**当程序运行时,就会产生缺页中断,需要的信息就会很自然地载入到真实内存中,而没有真正用到的信息可以一直保留再磁盘中。**因此就算真实内存只有1G,也可以运行4G的程序。
java的内存管理_第2张图片

堆heap(先进先出)和栈stack

堆和栈存储在JVM虚拟机的RAM(随机访问存储器)中,
(1)栈内存->是单个线程的私有内存,用来存储局部变量(基本数据类型:int、short、double、long、float、boolean、char、byte;注意没有String)和方法调用
当没有引用指向栈中的某个数据时,该数据就会消失。
栈的优势:存取速度比堆快。
(2)堆内存->可以被所有线程访问,用来存储java中的对象(即java对象可以被所有线程访问),无论是成员变量、局部变量、还是类变量,它们指向的对象都存储在堆内存中。
堆中的对象由垃圾回收器负责回收,因此其大小和生命周期不需要确定,具有很大的灵活性。

数据段(Data Segment)

通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。字符串常量和静态常量全部存放在data segment里

代码段(Code Segment)

存放代码。

非RAM存储(硬盘等永久存储空间)

非RAM存储用于存放持久化对象

常量池

string字符串常量池在内存中的位置:http://blog.csdn.net/litong09282039/article/details/46344121
常量池在java中用于保存在编译期已确定的、已编译的class文件中的一份数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量,如String s = "java"这种声明方式;执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。
为了确保常量的安全性(当其被多个变量引用的时候),常量池实施了一套保护机制:常量池中的常量不允许被改变。就算要改变某个变量的值为某个常量,也只是先在常量池中查看是否存在此常量,是则该变量指向它,否则创建它,再让该变量指向它。

基本数据类型与对象的区别

http://blog.csdn.net/xingzhemoluo/article/details/40050025
java中方法参数共有两种类型:
(1)基本数据类型(传值调用)
(2)对象引用(按值传递)
java中方法参数的使用情况:
(1)一个方法不能修改一个基本数据类型的参数。

//假定一个方法试图将一个参数值增加至3倍
private static void tripleVlaue(double x){
    x=x*3;
}
double percent =10;
tripleVlaue(percent);
//结果是percent仍然是10,没有改变。
//原因:当调用tripleVlaue(percent)时,参数变量x被初始化为percent值的拷贝,当方法结束后,x被丢弃。

(2)一个方法可以改变一个对象参数的状态。

public static void tripleSalary(Employee x){
   x.raiseSalary(200);
}
Bob = new Employee();
tripleSalary(Bob);
//结果是Bob和x同时引用的那个Employee对象的薪金提高了200%
//原因:当调用tripleSalary(Bob)方法时,参数变量x被初始化为Bob的拷贝,这里是一个Employee对象的引用(对象的地址)。

(3)一个方法不能让对象参数引用一个新的对象。


Employee a=new Employee("Alice",...);
Employee b=new Employee("Bob",...);
swap(a,b);
//结果是a仍然是引用new Employee("Alice",...),
//b仍然是引用new Employee("Bob",...),
//在方法swap(x,y)结束时,参数变量x和y就被丢弃了,也就是白费力气。

==和equals

(1)==比较的是对象的地址,也就是是否是同一个对象。
(2)equals比较的是对象的值。

对于字符串

其对象的引用都是存储在栈中的。
如果是编译期已经创建好的(直接用双引号定义的)就存储在常量池中。
如果是运行期(new出来的)才能确定的就存储在堆中。
对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
如以下代码:
String s1=“china”;
String s2=“china”;
String ss1=new String(“china”);
String ss2=new String(“china”);

垃圾回收

java的内存管理_第3张图片

你可能感兴趣的:(java)