java 内存机制
1.Java的内存机制
Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后(比如,在函数A中调用函数B,在函数B中定义变量a,变量a的作用域只是函数B,在函数B运行完以后,变量a会自动被销毁。分配给它的内存会被回收),Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
代码实例Test01:单个对象创建

class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+"年龄"+age);
}
}
public class Test01 {
public static void main(String[] args) {
Person per=new Person();
}
}

在上述程序中实例化了一个对象per,在实例化对象的过程中需要在内存中开辟空间,这其中就包括栈内存和对内存。具体的内存分配如下图所示:

我们可以从上图中发现,对象名称per被保存在了栈内存中(更加准确的说法是,在栈内存中保存的是堆内存空间的访问地址),而对象的具体内容,比如属性name和age,被保存在了堆内存中。因为per对象只是被实例化,还没有具体被赋值,所以都是默认值。字符串的默认值为null,int类型的默认值为0。前面也已经提到,堆内存空间必须使用new关键字才能开辟。
代码实例Test02:多个对象创建

class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
public class Test02 {
public static void main(String[] args) {
Person per1=new Person();
Person per2=new Person();
per1.name="张三";
per1.age=30;
per2.name="李四";
per2.age=33;
per1.tell();
per2.tell();
}
}


关键概念:类跟数组一样,都是属于引用类型,引用类型就是指一堆对内存可以同时被多个栈内存指向。下面来看一下引用传递的简单实例。
代码实例Test03:对象引用传递1

class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
public class Test03{
public static void main(String[] args) {
Person per1=new Person();
Person per2=per1;
per1.name="张三";
per1.age=30;
per2.age=33;
per1.tell();
per2.tell();
}
}

程序运行结果为:
姓名:张三,年龄:33
姓名:张三,年龄:33
从程序的运行结果可以发现,两个对象输出的内容一样,实际上所谓的引用传递,就是将一个堆内存空间的使用权交个多个栈内存空间,每个栈内存空间都可以修改堆内存空间的内容,此程序的内存分配图如下所示:


注意:上述实例中对象per2没有堆内存空间,这是因为对象per2只进行了声明操作,也没有进行实例化操作。只有使用new关键字实例化以后才会有对内存空间。
代码实例Test04:对象引用传递2

class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
public class Test04 {
public static void main(String[] args) {
Person per1=new Person();
Person per2=new Person();
per1.name="张三";
per1.age=30;
per2.name="李四";
per2.age=33;
per2=per1;
per1.tell();
per2.tell();
}
}

上述程序运行结果为:
姓名:张三,年龄:30
姓名:张三,年龄:30
从程序的输出结果可以发现可Test03一样。不过内存分配发生了一些变化,具体如下所示:

注意点:
- Java本身提供垃圾收集机制(Garbage Collection,GC),会不定期施放不用的内存空间,只要对象不用了,就会等待GC释放空间,如上面堆内存中的name="李四";age=33。
- 一个栈内存只能指向一个对内存空间,如果要想再指向其他的堆内存空间,则必须先断开已有的指向才能分配新的指向。
java中常用的内存区域
在java中主要存在4块内存空间,这些内存的名称及作用如下:
- 栈内存空间:保存所有的对象名称(更准确地说是保存了引用的堆内存空间的地址)
- 堆内存空间:保存每个对象的具体属性内容。
- 全局数据区:保存static类型的属性。
- 全局代码区:保存所有的方法定义。
java 内存机制的更多相关文章
- java基础知识(四)java内存机制
Java内存管理:深入Java内存区域 上面的文章对于java的内存管理机制讲的非常细致,在这里我们只是为了便于后面内容的理解,对java内存机制做一个简单的梳理. 程序计数器:当前线程所执行的字节码 ...
- java内存机制 垃圾回收
gc机制一 1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc ...
- java 内存机制简介
java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.java中对象是采用new或者反射的方法创 建的,这些对象的创建都是在堆中分配,所 ...
- java内存机制和GC垃圾回收机制
Java 内存区域和GC机制 转载来源于:https://www.cnblogs.com/zhguang/p/3257367.html 感谢 目录 Java垃圾回收概况 Java内存区域 Java对象 ...
- Java内存机制,内存地址
问题一:String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); // ...
- Java 内存机制、内存泄露
http://wenku.baidu.com/view/61f31da6284ac850ad02423e.html 自己注:hashset和hashmap不同 JDK1.6 API 中 HashSet ...
- JAVA内存机制
Java程序运行时,数据会分区存放,JavaStack(Java栈). heap(堆).method(方法区). 一.JVM内存模型 1.Java栈Java栈的区域很小,只有1M,特点是存取速度很快, ...
- Java 内存区域和GC机制分析
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- 「轉」Java的内存机制
0.参考资料: http://www.j2megame.org/index.php/content/view/2246/125.html 1.Java的内存机制 Java 把内存划分成两种:一种是栈内 ...
随机推荐
- Noip2016提高组 组合数问题problem
Day2 T1 题目大意 告诉你组合数公式,其中n!=1*2*3*4*5*...*n:意思是从n个物体取出m个物体的方案数 现给定n.m.k,问在所有i(1<=i<=n),所有j(1< ...
- 【经验】Maven Tomcat8+ 实现自动化部署
1.配置tomcat-users.xml 首先在Tomcat里配置deploy的用户(tomcat根目录/conf/tomcat-users.xml): <role rolename=" ...
- vertical-align 垂直居中
基线:字母‘x’的底部: 中线:与基线的距离为小写字母x高度的一半(即0.5ex),而ex同font-size相关,大部分浏览器认为1ex = 0.5em(em同样也是相对单位,不是绝对单位),因此会 ...
- MAC 安装j2ee.sh的办法
It says it needs the DISPLAY variable set - what do I need to set it to? Instead of saying: ./java_e ...
- 最简单的访问google的办法
我用的是猎豹浏览器,在工具下面的猎豹应用市场里面,搜索红杏,安装即可. 打开google产品地址时,如果地址栏里面右边的杏是绿色的,代表正常,如果是红色的,代表不正常. 可能是装了其他代理软件,如Sw ...
- css之px自动转rem—“懒人”必备
作为一名前端开发,尤其是在做移动端适配时,rem是我们经常用到的单位,它的好处大家可以自行搜索,网上已经有很多了.但是我们再将设计稿上的px转换成rem时,得手动的去计算,这是一个很耗时.费力的过程, ...
- python函数动态参数详解
Python的动态参数: 1,参数前一个"*":在函数中会把传的参数转成一个元组. def func (*args): print(args) func(123,1,2,'a') ...
- Lua 单例类
function SingleTon:new() local store = nil return function(self) if store then return store end loca ...
- 编写serversocket简单示例1
package j2se.core.net.tcp; import java.io.DataOutputStream;import java.io.IOException;import java.ne ...
- js汉语转拼音(全拼、首字母、拼音首字母)
新建js文件first_alphabet.js // JavaScript Document // 汉字拼音首字母列表 本列表包含了20902个汉字,用于配合 ToChineseSpell //函数使 ...