首先我们要明白一点,我们所使用的变量就是一块一块的内存空间!!

 
一、内存管理原理:
 
在java中,有java程序、虚拟机、操作系统三个层次,其中java程序与虚拟机交互,而虚拟机与操作系统间交互!这就保证了java程序的平台无关性!下面我们从程序运行前,程序运行中、程序运行内存溢出三个阶段来说一下内存管理原理!
 
1、程序运行前:JVM向操作系统请求一定的内存空间,称为初始内存空间!程序执行过程中所需的内存都是由java虚拟机从这片内存空间中划分的。
 
2、程序运行中:java程序一直向java虚拟机申请内存,当程序所需要的内存空间超出初始内存空间时,java虚拟机会再次向操作系统申请更多的内存供程序使用!
 
3、内存溢出:程序接着运行,当java虚拟机已申请的内存达到了规定的最大内存空间,但程序还需要更多的内存,这时会出现内存溢出的错误!

至此可以看出,Java 程序所使用的内存是由 Java 虚拟机进行管理、分配的。Java 虚拟机规定了 Java 程序的初始内存空间和最大内存空间,开发者只需要关心 Java 虚拟机是如何管理内存空间的,而不用关心某一种操作系统是如何管理内存的。  
 
二、 RUNTIME 类的使用:
 
Java 给我们提供了Runtime 类得到JVM 内存的信息
 方法名称  参数 作用  返回值 
 getRuntime   无  获取Runtime 对象   Runtime 对象 
 totalMemory   无  获取JVM 分配给程序的内存数量   long:内存数量 
 freeMemory  无  获取当前可用的内存数量   long:内存数量 
 maxMemory   无  获取JVM 可以申请到的最大内存数量  long:内存数量 
 
三、内存空间逻辑划分:
 
JVM 会把申请的内存从逻辑上划分为三个区域,即:方法区、堆与栈。 
 
方法区:方法区默认最大容量为64M,Java虚拟机会将加载的java类存入方法区,保存类的结构(属性与方法),类静态成员等内容。
 
堆:默认最大容量为64M,堆存放对象持有的数据,同时保持对原类的引用。可以简单的理解为对象属性的值保存在堆中,对象调用的方法保存在方法区。
 
栈:栈默认最大容量为1M,在程序运行时,每当遇到方法调用时,Java虚拟机就会在栈中划分一块内存称为栈帧(Stack frame),栈帧中的内存供局部变量(包括基本类型与引用类型)使用,当方法调用结束后,Java虚拟机会收回此栈帧占用的内存。 
四、java数据类型
1、基本数据类型:没封装指针的变量。
声明此类型变量,只会在栈中分配一块内存空间。
 
2、引用类型:就是底层封装指针的数据类型。
他们在内存中分配两块空间,第一块内存分配在栈中,只存放别的内存地址,不存放具体数值,我们也把它叫指针类型的变量,第二块内存分配在堆中,存放的是具体数值,如对象属性值等。
 
3、下面我们从一个例子来看一看:
public class Student {
String stuId;
String stuName;
int stuAge;
} public class TestStudent {
public static void main(String[] args) {
Student zhouxingxing = new Student();
String name = new String("旺旺");
int a = 10;
char b = 'm';
zhouxingxing.stuId = "9527";
zhouxingxing.stuName = "周星星";
zhouxingxing.stuAge = 25;
}
}
 
(1)类当然是存放在方法区里面的。
 
(2)Student zhouxingxing = new Student(); 
这行代码就创建了两块内存空间,第一个在栈中,名字叫zhouxingxing,它就相当于指针类型的变量,我们看到它并不存放学生的姓名、年龄等具体的数值,而是存放堆中第二块内存的地址,第二块才存放具体的数值,如学生的编号、姓名、年龄等信息。
 
(3)int a = 10; 
这是 基本数据类型 变量,具体的值就存放在栈中,并没有只指针的概念!
 
下图就是本例的内存布置图:
此外我们还要知道Student zhouxingxing = new Student(); 包括了声明和创建,即:Student zhouxingxing;和zhouxingxing = new Student();其中声明只是在栈中声明一个空间,但还没有具体的值,声明后的情况如下图所示:
创建后的情况如下图所示:
(4)引用类型中的数组也封装了指针,即便是基本数据类型的数组也封装了指针,数组也是引用类型。比如代码int[] arr = new int[]{23,2,4,3,1};如下图所示:
 五、java值传参与引用参数
 
(1)参数根据调用后的效果不同,即是否改变参数的原始数值,又可以分为两种:按值传递的参数与按引用传递的参数。
按值传递的参数原始数值不改变,按引用传递的参数原始数值改变!这是为什么呢?其实相当简单:
我们知道基本数据类型的变量存放在栈里面,变量名处存放的就是变量的值,那么当基本数据类型的变量作为参数时,传递的就是这个值,只是把变量的值传递了过去,不管对这个值如何操作,都不会改变变量的原始值。而对引用数据类型的变量来说,变量名处存放的地址,所以引用数据类型的变量作为传参时,传递的实际上是地址,对地址处的内容进行操作,当然会改变变量的值了!
 
(2)特例:string
 
public class TestString {
public static void main(String[] args) { String name = "wangwang";
TestString testString = new TestString(); System.out.println("方法调用前:" + name);
testString.change(name);
System.out.println("方法调用后:" + name);
} void change(String str) {
str = "旺旺老师";
System.out.println("方法体内修改值后:" + str);
}
}
 
结果:
方法调用前:wangwang 
方法体内修改值后:旺旺老师 
方法调用后:wangwang 
 
分析:
上例中,虽然参数String 是引用数据类型,但其值没有发生改变,这是因为String 类
是final 的,它是定长,我们看初始情况,即String name = "wangwang";这行代码运行
完,如下图:
当调用方法时testString.change(name),内存变化为:
在方法体内,参数str赋予一个新值,str = "旺旺老师"。因为String是定长,系统就会在堆中分配一块新的内存空间37DF,这样str指向了新的内存空间37DF,而name还是指向36DF, 37DF的改变对它已没影响:
最后,方法调用结束,str与37DF的内存空间消亡。Name的值依然为wangwang,并没有改变。
所以String虽然是引用类型参数,但值依然不变:
 

(3)无法交换的例子:

 
public class TestChange {
void change(Student stu1, Student stu2) {
stu1.stuAge ++;
stu2.stuAge ++;
Student stu = stu1;
stu1 = stu2;
stu2 = stu;
} public static void main(String[] args) { Student furong = new Student();
furong.stuName = "芙蓉姐姐";
furong.stuAge = 30; Student fengjie = new Student();
fengjie.stuName = "凤姐";
fengjie.stuAge = 26; TestChange testChange = new TestChange();
testChange.change(furong, fengjie); System.out.println(furong.stuName);
System.out.println(furong.stuAge); System.out.println(fengjie.stuName);
System.out.println(fengjie.stuAge);
} }

  

 
运行结果:

芙蓉姐姐 
31 
凤姐 
27 
 
分析:
 
 

JAVA内存管理 [转]的更多相关文章

  1. Java 内存管理

    java 内存管理机制 JAVA 内存管理总结 java 是如何管理内存的 Java 的内存管理就是对象的分配和释放问题.(两部分) 分配 :内存的分配是由程序完成的,程序员需要通过关键字 new 为 ...

  2. 简单的例子 关于Java内存管理的讲解

    我想做的是,逐行读取文件,然后用该行的电影名去获取电影信息.因为源文件较大,readlines()不能完全读取所有电影名,所以我们逐行读取. 就这段代码,我想要在位置二处使用base64,然后结果呢? ...

  3. java内存管理机制

    JAVA 内存管理总结 1. java是如何管理内存的 Java的内存管理就是对象的分配和释放问题.(两部分) 分配 :内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间 ( ...

  4. Java内存管理的9个小技巧

    Java内存管理的9个小技巧很多人都说“Java完了,只等着衰亡吧!”,为什么呢?最简单的的例子就是Java做的系统时非常占内存!一听到这样的话,一定会有不少人站出来为Java辩护,并举出一堆的性能测 ...

  5. 关于Java内存管理的几个小技巧

    这里将介绍几则Java内存管理的小技巧,让你让你从Java入门开始告别陋习,为Java程序提速.有不少人都说"Java完了,只等着衰亡吧!",为什么呢?最简单的的例子就是Java做 ...

  6. java内存管理(堆、栈、方法区)

    java内存管理 简介 首先我们要了解我们为什么要学习java虚拟机的内存管理,不是java的gc垃圾回收机制都帮我们释放了内存了吗?但是在写程序的过程中却也往往因为不懂内存管理而造成了一些不容易察觉 ...

  7. Java内存管理及对Java对象管理

    Java内存管理及对Java对象管理 1Java内存管理 1.1Java中的堆和栈 通常来说,人们会将Java内存氛围栈内存(Stack)和堆内存(Heap). 栈内存用来保存基本类型的变量和对象的引 ...

  8. 揭开Java内存管理的面纱

    前言 相对于C.C++这些高性能语言,Java有着让此类程序员羡慕的功能:内存自动管理.似乎这样,Java程序员不用再关心内存,也不用去了解相关知识.但结果真的是这样吗?特别对于我们这种Android ...

  9. java基础(一):谈谈java内存管理与垃圾回收机制

    看了很多java内存管理的文章或者博客,写的要么笼统,要么划分的不正确,且很多文章都千篇一律.例如部分地方将jvm笼统的分为堆.栈.程序计数器,这么分太过于笼统,无法清晰的阐述java的内存管理模型: ...

  10. Java内存管理的进一步理解-模拟过程图解

    Java内存管理的进一步理解-模拟过程图解--转载 java的内存管理分为: 1.堆内存:2.栈内存:3.方法区:4.本地方法区 /* 1:方法区      方法区存放装载的类数据信息包括:      ...

随机推荐

  1. core Animation之CAAnimationGroup(动画群组)

    可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行 属性解析: animations:用来保存一组动画对象的NSArray 默认情况下,一组动画对象 ...

  2. 分布式理论(六)—— Raft 算法

    前言 我们之前讲述了 Paxos 一致性算法,虽然楼主尝试用最简单的算法来阐述,但仍然还是有点绕.楼主最初怀疑自己太笨,后来才直到,该算法的晦涩难懂不是只有我一个人这么认为,而是国际公认! 所以 Pa ...

  3. 21.Module 的加载实现

    Module 的加载实现 Module 的加载实现 上一章介绍了模块的语法,本章介绍如何在浏览器和 Node 之中加载 ES6 模块,以及实际开发中经常遇到的一些问题(比如循环加载). 浏览器加载 传 ...

  4. .1-浅析express源码之入口文件

    鸽了鸽了,webpack源码大垃圾,看了那么久,感觉自己越来越渣……还是换个口味,node了解一下? 尝试从express框架源码入手,学习一下node的http模块相关的知识. 入口文件 先从框架的 ...

  5. C# 四舍五入 保留两位小数(转载)

    一.C#默认四舍五入 1 Math.Round(45.367,2) //Returns 45.372 Math.Round(45.365,2) //Returns 45.36二.C#中的Round() ...

  6. [android] 优酷环形菜单-旋转动画

    获取房子,菜单图标ImageView对象,获取三个圆环RelativeLayout对象 给菜单图标(icon_menu)设置点击事件 定义一个成员变量isLevel3Show来存储第三级菜单是否显示 ...

  7. spring中@Scope控制作用域

    注解形势:通过@Scope注解控制作用域,默认使用单实例模式,可修改为多实例模式 /** * Specifies the name of the scope to use for the annota ...

  8. Mybatis中trim标签的用法

    select * from t_user <trim prefix="WHERE" prefixOverrides="and"> <if te ...

  9. HDU1114(KB12-F DP)

    Piggy-Bank Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  10. MRO + super面试题(详解)

    class Init(object): def __init__(self, v): print("init") self.val = v class Add2(Init): de ...