「轉」Java的内存机制
0.参考资料:
http://www.j2megame.org/index.php/content/view/2246/125.html
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的内存机制的更多相关文章
- python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样
python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样
- Java的内存机制(转)
0.参考资料: http://www.j2megame.org/index.php/content/view/2246/125.html 1.Java的内存机制 Java 把内存划分成两种:一种是栈内 ...
- Java学习——内存机制
Java学习——内存机制 摘要:本文主要介绍了Java的内存机制. 部分内容来自以下博客: https://www.cnblogs.com/xrq730/p/4827590.html https:// ...
- 「MoreThanJava」Java发展史及起航新世界
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- Java的内存机制
Java 把内存划分成两种:一种是栈内存,另一种是堆内存.在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空 ...
- Java的内存机制详解
Java把内存分为两种:一种是栈内存,另一种是堆内存.在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间, ...
- 「福利」Java Swing 编写的可视化算法工程,包含树、图和排序
之前在整理<学习排序算法,结合这个方法太容易理解了>这篇文章时,发现了一个用 Java Swing 编写的可视化算法工程,真心不错!包含了常用数据结构和算法的动态演示,先来张图感受下: 可 ...
- 「 深入浅出 」java集合Collection和Map
本系列文章主要对java集合的框架进行一个深入浅出的介绍,使大家对java集合有个深入的理解. 本篇文章主要具体介绍了Collection接口,Map接口以及Collection接口的三个子接口Set ...
- 「Nosql」Redis小记-内存解析&内存消耗篇
*博客搬家:初版发布于 2017/08/12 18:32 原博客地址:https://my.oschina.net/sunqinwen/blog/1507171 Redis内存消耗分析 注:本文 ...
随机推荐
- sql语句执行顺序
首先来一张朋友传给我的图 FORM: 对FROM的左边的表和右边的表计算笛卡尔积.产生虚表VT1 ON: 对虚表VT1进行ON筛选,只有那些符合<join-condition>的行才会被记 ...
- POJ3069 POJ2586 解题报告(异曲同工的贪心算法)
[POJ 3069](2586见下) 原题在此:http://poj.org/problem?id=3069 题目大意: 一个直线上有N个点.点i的距离是Xi.从这些点中选取若干个加上标记.要求:对于 ...
- MySQL的学习--用户创建授权
前一段时间,将项目改成SAAS的架构,每个billing account都可以获得一个子域,一个单独的数据库,一个单独的数据库用户和对应数据库的权限. 现在有时间了,将数据库相关的命令用博客备份一下. ...
- 360wifi使用方法|360wifi使用教程
360随身WiFi是一款超迷你.操作极其简单的无线路由器,只需把360随身WiFi插到一台可以上网的电脑上,不用做任何设置,就把连接有线网络的电脑转变成接入点,实现与其他终端的网络共享.简单方便实现手 ...
- 网络通信之Socket与LocalSocket的比较
Socket与LocalSocket都可以实现网络通信,两个有什么区别呢? LocalSocket其通信方式与Socket差不多,只是LocalSocket没有跨越网络边界. 于是,思考到一个问题:a ...
- 推荐20款基于 jQuery & CSS 的文本效果插件
jQuery 和 CSS 可以说是设计和开发行业的一次革命.这一切如此简单,快捷的一站式服务.jQuery 允许你在你的网页中添加一些真正令人惊叹的东西而不用付出很大的努力,要感谢那些优秀的 jQue ...
- Windows Azure HandBook (5) Azure混合云解决方案
<Windows Azure Platform 系列文章目录> 在很多情况下,我们都会遇到本地私有云和公有云做互通互联的混合云场景.对于这种混合云的场景,微软的Windows Azure会 ...
- SQL Server安全(2/11):身份验证(Authentication)
在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切.但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念.这篇文章提供了基础,因此你可以对SQL Se ...
- [UWP]涨姿势UWP源码——RSS feed的获取和解析
本篇开始具体分析涨姿势UWP这个APP的代码,首先从数据的源头着手,即RSS feed的获取和解析,相关的类为RssReader,所有和数据相关的操作均放在里面. 涨姿势网站提供的RSS feed地址 ...
- Android开发中的全屏背景显示方案
引子 不管是Android还是iOS平台中,都可以看到一些应用在启动的时候会先出现一个启动画面(Splash Activity),如QQ.微信等.这个启动画面中往往会将ActionBar和Status ...