一. jdk的内存:jdk的bin目录常见命令

  1. javac.exe:编译java源代码的,生成java字节码文件(*.class)

  2. java.exe:启动一个jvm,来运行指定class字节码文件

  3. javap.exe:(javap -c  java type.class)反汇编Java字节码成Java源代码。

二. Jvm的内存

  1. 栈内存:函数的{ }之间定义的变量均在JVM的stack栈内存中存储(在定义其变量的时候,开辟空间,当执行到函数右大括号时,栈内存回收)

  注:简单类型定义的变量直接存储数值,引用类型定义的变量存储的是地址。

  2. 堆内存:存储新new的对象(new的时候开辟空间, 闲置时则靠GC(Garbage Collection垃圾回收器)来回收堆内存)

  注:堆里只存储新new的对象

    JVM内存简单示例:

 3. int型

   1. int a=10;

    int b=10;

    //简单类型,变量里存储的是数值

    System.out.println(a==b);

    //因为存储的是数值,所以此处比较的是数值大小。

    //结果:true

   2. Integer b=new Integer(10);

    Integer d=new Integer(10);

    //引用类型,变量里存储的是地址,new的对象(10)在堆里。

    System.out.println(b==d);

    //因为存储的是地址,b,d 地址不相等。/

    /结果:false

    System.out.println(b.equals(d));

    //此处是对b, d 进行调用函数equals(),比较其数值的大小。

    //结果:true

   3. Integer b=new Integer(10);

    Integer e=10;

Integer f=10;

    //此处调用Integer.valueOf()函数,相当于

     Integer.valueOf(10)

     if(data>=-128&&data<=127)

      {

       return Integer.cache(data);//返回的是缓存池里的固定地址

      }

     else{

       return new Integer(data);//返回的是新new出来的地址

       }

    //注:用Integer e=?;定义变量时,当变量的值?在-128——//127之间时,e的地址均在常量池里找。

    System.out.println(e==f);

    //因为e,f的变量值均在-128——127之间,所以在常量池中查找,

    //且e ,f 存储的是地址,即结果为true

    System.out.println(e==b);

    //因为b是用Integer e=?;方式定义的,且在-128——127范//围内,所以地址在常量池里查找。而b是新new的地址,所以结果:false。

  装包:Integer e=10;//(将一个数值赋给引用变量,此时就要进行装包,装包的实质就是调用 Integer.valueOf(10);找到在缓存池中的位置,返回地址。)

     Integer.valueOf(10)

     if(data>=-128&&data<=127){

return Integer.cache(data);//返回的是缓存池里的固定地址

     }else{

return new Integer(data);//返回的是新new出来的地址

}

拆包:int b=a;    (当两个变量进行比较,一个为数值,一个为地址时,此时就要对引用地址的变量进行拆包)

//a.intValue()

         { 

          return  Value;//返回其数值

         }

    例题分析:

        *在jdk1.5的环境下,有如下4条语句:

        Integer i01=59;   //  要装包

        int i02=59;

        Integer i03= Integer.valueOf(59);

        Integer i04= new Integer (59);

        以下输出结果为false的是( C )

        A. System.out.println(i01== i02);

        //1是装包后,地址在常量池里找的。2存的是数值。所以此时两者进行比较要对i01进行拆包,然后在进行比较。True

        B. System.out.println(i01== i03);

        //1是装包后,地址在常量池里找的。3是1的具体语句,所以3也是装包后,地址在常量池里找。  True

        C. System.out.println(i03== i04);

        //3是装包后,地址在常量池里找的。

        //4是新new的,地址是新开辟的。  False

        D. System.out.println(i02==i04);

       //2存的是数值。4是新new的地址。所以此时进行拆包,两者均拆为数值,然后进行比较。  true

  4.string型

    1.String  str1=new String("hello world");//str1存储的是新new的地址

      String  str2=new String("hello world");  //str2存储的是新new的地址

      String  str3="hello world";                     //str3进行了装包,并且地址是在常量池里查找的

        System.out.println(str1=str2);

      System.out.println(str1=str3);

      System.out.println(str1.equals(str2));

 5.Byte型.Short型.long型.Float型.Double型与Integer型用法一样。

    但Byte型的范围为-128——127,所以Byte data1=Byte.valueOf(59);均在常量池中查找。

6.例题1

 public class liti {
public static void main(String[] args) {
int a=10;
int b=20;
swap(a,b); //调用swap方法对变量,a b 的值进行交换
System.out.println(a+" "+b);
}
private static void swap(int a,int b)
{
int temp=a;
a=b;
b=a; }
}

代码结果

 分析:

当程序开始执行时,首先调用了main()方法,所以JVM在栈内存中给main()方法开辟了一块内存,在main()方法内存中

定义了两个变量 a, b ,并分别给其赋值10,20。接着又调用了swap()方法,于是JVM在栈内存中给swap()方法也开辟了一块

内存,在swap()方法内存中,定义了一个变量temp,并将a的值赋给temp,然后将 a b 的值进行交换,当出了swap()方法的

右大括号时,swap内存被回收,因为swap()方法中无任何返回值,所以随着内存被回收,在swap内存中进行的一切运算也

将归零。而此时main()方法中 a 和 b 变量的值仍为10 和20,这时候打印出来的结果仍为a=10,b=20.

 7.例题二

 public class liti {
public static void main(String[] args) {
int[] arr=new int[2];
arr[0]=10;
arr[1]=20;
swap(arr,0,1); //交换数组元素arr[0],arr[1]的值
System.out.println(arr[0]+" "+arr[1]);
} private static void swap(int[] arr, int i, int i1) {
int temp=arr[0];
arr[0]=arr[1];
arr[1]=temp; }
}

运行结果

分析

当程序在执行时,首先调用了main()方法,所以Jvm在栈内存中给main()方法开辟了一块内存,在这块内存中

定义了一个数组变量,其变量中存储的是数组的地址,然后根据地址又在堆内存中给数组元素进行了赋值,接着

调用swap()方法,所以Jvm在栈内存中给swap()方法开辟了一块内存 ,  在这块内存中定义了一个数组变量,并将

main()方法中的数组变量arr的值(地址)赋给它,swap()方法根据变量arr中的地址,在堆内存中找到该数组,并将

数组元素arr[0] 和arr[1]的值进行交换。此时swap()方法执行完毕,swap内存被Jvm回收。因为main()方法和swap()

方法引用的是一个数组地址,所以此时main()方法中的数组的值也被就改变了,所以在main()方法中打印arr数组元

素的值,结果为arr[0]=20;arr[1]=10。

8.例题

 import java.util.Arrays;
public class liti {
public static void main(String[] args) {
String str="good";
char[] ch={'a','b','c'};
change(str,ch);
System.out.println(str+" "+ Arrays.toString(ch));
} private static void change(String str, char[] ch) {
str="test.ok";
ch[0]='g';
}
}

代码结果:

 分析:

当程序在执行时,首先调用了main()方法,所以Jvm在栈内存中给main()方法开辟了一块内存,在这块内存中

先定义了一个字符类型变量,该变量中存储的是该字符串在堆中的地址,然后定义了一个字符数组变量,

其变量中存储的是数组的地址,然后根据地址又在堆内存中给字符数组元素进行了赋值。接着调用change()方法,

所以Jvm在栈内存中给change()方法开辟了一块内存,在change内存中,定义了一个字符串变量,并将main()方法

中的字符串变量的值(地址)赋给它,还定义了一个字符数组变量,同样的,并将main()方法中的字符数组变量的值

(地址)赋给它,然后在该方法中又将字符串“good”在堆中(字符串常量池)的地址赋给str,接着又根据ch的地址

在堆中找到字符串数组,并将堆中的数组元素ch[0]='a';变成ch[0]='g';随着change()方法执行完毕,change()方法

的内存被回收,而此时main()方法中的str变量仍存储的是“good“的地址,虽然ch也存储的仍是数组在堆中的地址

但数组内的值却发生了变换。所以打印出来的结果str不变,ch变。

Java的引用类型的内存分析的更多相关文章

  1. Java运行原理及内存分析

    Java运行原理及内存分析 一.Java运行原理 二.Java内存分析

  2. Eclipse中的快捷键快速生成常用代码(例如无参、带参构造,set、get方法),以及Java中重要的内存分析(栈、堆、方法区、常量池)

    (一)Eclipse中的快捷键:  ctrl+shift+f自动整理选择的java代码 alt+/ 生成无参构造器或者提升信息 alt+shift+s+o 生成带参构造 ctrl+shift+o快速导 ...

  3. Java面向对象_对象内存分析—值传递和引用传递

    对象内存分析,我一直学的比较模糊,今天抽空整理一下,希望能理清. 先说一下,内存分析从何而来,这对于我们这些刚接触java的人来说都比较模糊,就从new关键字说起吧. new关键字表示创建一个对象或者 ...

  4. Java数组(基本+内存分析)

    一.数组概念   数组即为多个相同数据类型数据的数据按一定顺序排列的集合. 二.数组的特点   1.数组有数组名.索引.元素.素组长度:   2.数组的元素可以是基本数据类型也可以是引用数据类型:   ...

  5. Java/Android引用类型及其使用分析

    Java/Android中有四种引用类型,分别是: Strong reference     - 强引用Soft Reference        - 软引用Weak Reference      - ...

  6. java基础知识回顾之---java String final类 容易混淆的java String常量池内存分析

    /** *   栈(Stack) :存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放  在常量池中). 堆(heap):存 ...

  7. java构造器级简单内存分析

    java构造器的使用(基础篇) 构造方法也叫构造器,是创建对象时执行的特殊方法,一般用于初始化新对象的属性. 基本定义语法: 访问控制符 构造方法名([参数列表]){ 方法体 } 注:"访问 ...

  8. java堆转储与内存分析

    jmap -dump:format=b,file=dumpfile.hprof pid       将进程的堆转储到dumpfile.hprof文件里 jmap -heap pid  查看堆内存占用情 ...

  9. java数据传递例子+内存分析

    一.引用传递 1.例子1 package com.jikexueyuan.ref; class Ref1{ int temp = 10; } public class RefDemo01 { publ ...

随机推荐

  1. Vue 编程式的导航

    1.应用场景 在同一路由的情况下,不同的参数之间进行切换 注意:别忘记初始化路由页面 2.用法 a.定义方法 b.实现方法 c.初始化路由页面 3.案例 <template> <di ...

  2. Linux下搭建Jmeter+Ant+Jenkins自动化测试框架

    前言 在之前的文章中,我们学习了通过Ant调用Jmeter脚本生成HTML测试报告,但未实现自动执行脚本生成报告,同时生成的报告是在Linux下,查看报告很不方便.因此,我们将结合Jenkins来进一 ...

  3. Java单体应用 - 开发工具 - 01.IntelliJ IDEA

    原文地址:http://www.work100.net/training/monolithic-tools-intellij-idea.html 更多教程:光束云 - 免费课程 IntelliJ ID ...

  4. 机器学习- Sklearn (交叉验证和Pipeline)

    前面一节咱们已经介绍了决策树的原理已经在sklearn中的应用.那么这里还有两个数据处理和sklearn应用中的小知识点咱们还没有讲,但是在实践中却会经常要用到的,那就是交叉验证cross_valid ...

  5. CQBZOJ 避开怪兽

    题目描述 给出一个N行M列的地图,地图形成一个有N*M个格子的矩阵.地图中的空地用'.'表示.其中某些格子有怪兽,用'+'表示.某人要从起点格子'V'走到终点格子'J',他可以向上.下.左.右四个方向 ...

  6. Python学习,第七课 - 文件操作

    Python中对文件的相关操作详解 文件的操作在今后的Python开发中也是使用非常频繁的. 先说下对文件操作的流程 打开文件,得到文件的一个句柄,赋值给一个变量 然后通过句柄对文件进行操作(内容的增 ...

  7. HDU Queuing(递推+矩阵快速幂)

    Queuing Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  8. MySQL 清理缓存—flush tablesFlush tables的影响

    摘自:http://blog.chinaunix.net/uid-31401119-id-5781305.html 1  Flush tables简介 官方手册中关于Flush tables的介绍, ...

  9. Shell脚本深入教程(1):快速入门

    Shell脚本基础入门 Bash注释 Bash只支持单行注释,使用#开头的都被当作注释语句: # 整行注释 echo hello world # 行尾注释 通过Bash的一些特性,可以取巧实现多行注释 ...

  10. 下载STRING数据库检索互作关系结果为空,但是在STRING网站却能检索出互作关系,为什么呢???关键词用的是蛋白ID(ENSP开头)

    首先介绍下两种方法: 一.本地分析 1.在STRING数据库下载人的互作文件,如下图,第一个文件 https://string-db.org/cgi/download.pl?sessionId=HGr ...