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

 
一、内存管理原理:
 
在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内存管理(堆、栈、方法区)

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

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

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

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

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

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

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

  8. Java内存管理-一文掌握虚拟机创建对象的秘密(九)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! [福利]JVM系列学习资源无套路赠送 回顾一下: 本文是接着上一篇内容:Java内存管 ...

  9. Java内存管理-掌握虚拟机类加载机制(四)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇介绍了整个JVM运行时的区域,以及简单对比了JDK7和JDK8中JVM运行时区域 ...

随机推荐

  1. 在pydev安装完成后在eclipse不显示的问题

    Java配置: http://www.jb51.net/os/win10/370409.html http://blog.csdn.net/wwd0501/article/details/521308 ...

  2. Accessing data in Hadoop using dplyr and SQL

    If your primary objective is to query your data in Hadoop to browse, manipulate, and extract it into ...

  3. HDU 2846 Repository(字典树,每个子串建树,*s的使用)

    Repository Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  4. python编程遇见的异常

    import sys print('目前系统的编码为:',sys.getdefaultencoding()) # 目前系统的编码为: utf-8 name = 'this is a test!' pr ...

  5. 【洛谷】P1247 取火柴游戏(Nim)

    题目 传送门:QWQ 分析 蒟蒻根本不会博弈论..... 只知道异或和判断Nim游戏.. 不是很懂输出的选择,所以发一篇博客以待复习 代码 #include <bits/stdc++.h> ...

  6. 如何用git命令行上传本地代码到github

    注意:安装的前提条件是配置好Git的相关环境或者安装好git.exe,此处不再重点提及 上传的步骤: 本文采用git 命令界面进行操作,先执行以下两个命令,配置用户名和email[设置用戶名和e-ma ...

  7. Linux 清除N天前的 日期文件夹(yyyy-MM-dd)

    本人碰到模糊目录移除,小记一下 1:准确目录情况  2:模糊目录情况 先来介绍准备目录情况 本人在网上找到的demo, 目录结构(在/root/zlogs) 脚本文件b.sh #!/bin/bash ...

  8. STL string 常用函数(转)

    string类的构造函数: string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 此外,string类还支持默认构造 ...

  9. 【Git】一、Git简介

    一.什么是Git Git是一款免费的开源分布式版本控制系统,可以有效的,高速的处理从很小到非常大的文件. 二.Git VS SVN 1. Git 是分布式的,SVN 是集中式的 2. Git 存储的是 ...

  10. Linux下强大的查找命令find 用法和常见用例

    Linux系统下find是较为常用的指令,find命令在目录结构中搜索文件,并执行指定的操作,掌握它的形式与用法对我们很有用处. 因为Linux下面一切皆文件,经常需要搜索某些文件来编写,所以对于Li ...