一. 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. 一次jvm调优过程

    jvm调优实战 前端时间把公司的一个分布式定时调度的系统弄上了容器云,部署在kubernetes,在容器运行的动不动就出现问题,特别容易jvm溢出,导致程序不可用,终端无法进入,日志一直在刷错误,ku ...

  2. 全网最详细!Centos7.X 搭建Grafana+Jmeter+Influxdb 性能实时监控平台

    背景 日常工作中,经常会用到Jmeter去压测,毕竟LR还要钱(@¥&*...),而最常用的接口压力测试,我们都是通过聚合报告去查看压测结果的,然鹅聚合报告的真的是丑到家了,作为程序猿这当然不 ...

  3. iOS使用fastlane自动化打包到fir(最全最详细流程)

    # iOS使用fastlane自动化打包到fir(最全最详细流程)1. **首先确认是否安装了ruby,终端查看下ruby版本**> ruby -v终端输出:ruby 2.4.1p111 (20 ...

  4. python3装饰器-进阶

    一.wraps 作用:优化装饰器 from functools import wraps # 导入wraps def wrapper(f): @wraps(f) # wraps的语法糖 def inn ...

  5. makefile自动依赖生成

    自动依赖生成 基于make的构建环境要正确工作, 一个很重要(也很烦人)的任务是, 在makefile中正确列 举依赖. 这个文档将介绍了一个非常有用的让make自身来创建和维护这些依赖的方法. 文章 ...

  6. FileZilla 报错“the server's certificate is unknown”

    FileZilla 是非常好用的一款FTP SFTP 管理工具. 但是filezilla会报错“the server's certificate is unknown” 并且会在window中看到以下 ...

  7. 创建dynamics CRM client-side (四) - Namespace Notation in JS

    我们在开发的时候会写很多functions. 但是这些functions 管理起来很麻烦. 微软内部建议我们使用namespace notation的形式管理我们的代码 // Converting f ...

  8. php--->底层的运行机制与数据结构原理

    PHP 底层的运行机制与数据结构原理 1. PHP的设计理念及特点 多进程模型:由于PHP是多进程模型,不同请求间互不干涉,这样保证了一个请求挂掉不会对全盘服务造成影响,当然,随着时代发展,PHP也早 ...

  9. ios--->泛型

    泛型 开发中使用场景: 1.限制集合中的类型,只能检测方法的调用,因为声明的泛型只能存在方法中 2.当一个类在声明的时候,某个对象的属性不确定,只有创建对象的时候才能确定,就可以使用泛型. 使用泛型的 ...

  10. Jquery 替换全部字符

    item.replace('P','')   只会替换第一个'P'字符 item.replace(/P/gm,'') 替换全部'P'字符