相信大多数的java初学者都会有这种经历:碰到一段代码的时候,不知该从何下手分析,不知道这段代码到底是怎么运行最后得到结果的..... 等等吧,很多让人头疼的问题,作为一名合格的程序员呢,遇到问题一定要思路清晰,不要将错就错,蒙混过关,这一点很重要!

鉴于笔者最近恶补了java基础,在这儿给大家总结了一些java代码内存分析的经验,希望可以对家有所帮助。

在分析内存之前呢,通过这个图让大家明白计算机是怎么处理一个程序的。



简单总结一下:1.计算机首先从硬盘拿到程序,加载(load)到内存区

2.操作系统找到main方法开始执行

3.执行代码过程中的内存管理:

内存中分四块:分别是heap(堆)、stack(栈)、data segment

(数据区)、code segmen(代码区),各个区所存储的内容图中已

标注。

接下来,

给大家举几个例子程序,分别进行内存分析

**

程序一:

**

public class Person {

	static int id;
static int age; Person(int _id, int _age) {
id = _id;
age = _age;
} public static void main(String[] args) {
Person tom = new Person(1,25);
System.out.println("id= " + id + " age= " + age); } }

内存分析图:

第一步:从main方法入手,首先看到要实现一个Person类对象,该对象的名字是tom,则在stack中立马分配出一块空间用来存tom这个对象名,它指向heap中的Person对象(上文提到heap中存储new出来的东西)

注:图中局部变量tom的内容为xxx,xxx实际为Person对象在堆中的地址,在此处用xxx

代替。

第二步:调用Person中的构造方法,此时定义了两个局部变量(要存储到stack中)_id和_age,则立马在stack中分配两块空间用于存储这两个局部变量,接下来把1和25分别传给这两个变量

第三步:执行id=_id; age=_age;这两句,把_id和_age的值传给Person对象

第四步:局部变量_id和_age消失(java的垃圾回收机制)

到此完成Person对象的创建,执行输出语句,程序运行结束。

**

程序二:super引用,动态绑定及多态

**

说到多态,就先给大家巩固一下动态绑定和多态的概念吧:

动态绑定:在执行期间(非编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

简单的来说,动态绑定就是根据实际new的对象所属的类调用方法,帮助程序的扩展性达到极致。

多态的话,要知道多态产生的三个条件:

1.有继承

2.有重写

3.父类引用指向子类对象

//abstract 关键字 ---> 抽象类,抽象类一定被继承,抽象方法一定被重写
class Animal { //可以这样声明 absrtact class Animal
private String name;
Animal(String name) {
this.name = name;
} public void enjoy() {
System.out.println("叫声...");
}
} class Cat extends Animal{
private String eyescolor; Cat(String n,String c) {
super(n);
eyescolor = c;
}
public void enjoy() {
System.out.println("猫叫声....");
}
} class Dog extends Animal {
private String furCorlor; Dog(String n, String f) {
super(n);
furCorlor = f;
} public void enjoy() {
System.out.println("狗叫声...");
}
} class Lady {
private String name;
private Animal pet; Lady(String name, Animal pet) {
this.name = name;
this.pet = pet;
} public void petEnjoy() {
pet.enjoy();
}
}
public class TestAnimal {
public static void main(String[] args) {
Cat c = new Cat("catname","blue");
Dog d = new Dog("dogname","black");
c.enjoy();
d.enjoy(); Lady l1 = new Lady("l1",c);
Lady l2 = new Lady("l2",d);
l1.petEnjoy();
l2.petEnjoy();
}
}

内存分析图:

老样子,从main方法入手:

第一步,Cat c = new Cat("catname","blue");

当你new一个子类对象出来的时候,其内部就已经包含父类对象,并且该子类对象的super引用会指向其父类对象。

此处分两小步给大家说明:(stack中局部变量的产生过程不再赘述,可参考程序一)

(1)new出来的Cat对象中包含Animal对象,Animal对象有一个成员变量name,自动初始化为null,C对象有一个成员变量eyescolor,自动初始化为null。



(2)传“catname”和“blue”这两个参数,“blue”直接赋值给eyescolor,而“catname”传进去后,通过super(n)方法,调用其父类对象的构造方法,使name值等于“catname”

第二步,Dog d = new Dog("dogname","black");

内存分析同第一步(此处省略)

第三步,c.enjoy(); d.enjoy();

此时,c指向的是Cat对象,但是Cat对象中包含其父类Animal对象,这两个对象都含有enjoy()方法,那么应该调用哪一个呢?这就涉及到了java的动态绑定机制了,你new出来的对象实际是Cat对象,那么就调用Cat对象的方法,而不是调用Animal对象的enjoy()方法;同理,d.enjoy()调用的是Dog对象的enjoy()方法。

所以,输出结果为

第四步,Lady l1 = new Lady("l1",c);

Lady l2 = new Lady("l2",d);

内存分析图:

此处Animl的引用pet指向了其子类对象c,也就是上文提到的“父类引用指向子类对象”,并且,有继承、有重写,这就是多态。

每一个创建出来的对象都有this引用,指向他自身

第五步, l1.petEnjoy();

l2.petEnjoy();

调用Lady的petEnjoy()方法,输出对应信息,最终输出结果为

程序三:数组

3.1 一维数组

public class Test {
public static void main(String[] args) {
Date[] days = new Date[3];
for(int i=0;i<3;i++) {
days[i] = new Date(2020,4,i+1);
}
}
}
class Date {
int year,month,day;
Date(int y, int m, int d) {
year = y;
month = m;
day = d;
}
}

内存分析图

days指向堆中的一个数组,该数组中存放的是每一个Date对象的地址,每一个地址指向一个Date对象。(详细赋值过程可参考程序一)

3.2 二维数组

二维数组实际上是一维数组的数组

public class Array {
public static void main(String[] args) {
int[][] a = new int[][] {
{1,2,3},
{4,5,6},
{7,8,9}
}; }
}

内存分析图

栈空间中a指向一个一维数组,该数组每块区域存放的是int型数组的地址。

笔者创作初期,如有不当之处,望批评指正。

Java 内存分析(程序实例),学会分析内存,走遍天下都不怕!!!的更多相关文章

  1. 关于C、Java、Python程序运行耗时及内存用量

    最近没有刷题,而是在PTA找几个题目寻找有关程序输入流问题以及各种语言在运行时对计算机消耗内存的问题, 以免很多同学解题的时候发现自己做的对但是出现运行超时的问题:针对运行内存,肯定用C/C++的同学 ...

  2. Java RMI(远程方法调用) 实例与分析 (转)

    目的: 通过本文,可以加深对Java RMI的理解,知道它的工作原理,怎么使用等. 也为了加深我自己的理解,故整理成文.不足之处,还望指出. 概念解释: RMI(RemoteMethodInvocat ...

  3. Java RMI(远程方法调用) 实例与分析

    目的: 通过本文,可以加深对Java RMI的理解,知道它的工作原理,怎么使用等. 也为了加深我自己的理解,故整理成文.不足之处,还望指出. 概念解释: RMI(RemoteMethodInvocat ...

  4. java 调用c++程序实例

    1.java程序: package com.zhangshitong; import java.io.File; public class Java2cpp { static{ System.load ...

  5. Android 内存管理 &Memory Leak & OOM 分析

    转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...

  6. 《疯狂Java:突破程序员基本功的16课》读书笔记-第二章 对象与内存控制

    Java内存管理分为两个方面:内存分配和内存回收.这里的内存分配特指创建Java对象时JVM为该对象在堆内存中所分配的内存空间.内存回收指的是当该Java对象失去引用,变成垃圾时,JVM的垃圾回收机制 ...

  7. flask实战-个人博客-使用工厂函数创建程序实例 --

    使用工厂函数创建程序实例 使用蓝本还有一个重要的好处,那就是允许使用工厂函数来创建程序实例.在OOP(Object-Oriented Programming,面向对象编程)中,工厂(factory)是 ...

  8. linux下分析java程序占用CPU、内存过高

    一.CPU过高分析 1)使用TOP命令查看CPU.内存使用状态可以发现CPU占用主要分为两部分,一部分为系统内核空间占用CPU百分比,一部分为用户空间占用CPU百分比.其中CPU状态中标示id的为空闲 ...

  9. 《深入理解Java虚拟机》(六)堆内存使用分析,垃圾收集器 GC 日志解读

    堆内存使用分析,GC 日志解读 重要的东东 在Java中,对象实例都是在堆上创建.一些类信息,常量,静态变量等存储在方法区.堆和方法区都是线程共享的. GC机制是由JVM提供,用来清理需要清除的对象, ...

  10. java内存泄漏的定位与分析

    1.为什么会发生内存泄漏 java 如何检测内在泄漏呢?我们需要一些工具进行检测,并发现内存泄漏问题,不然很容易发生down机问题. 编写java程序最为方便的地方就是我们不需要管理内存的分配和释放, ...

随机推荐

  1. golang开发:环境篇(三)开发利器Goland安装

    这节主要介绍下golang开发的最主要的IDE,Goland.可以有效提高开发效率.用过一段时间 IntelliJ+GO插件,其实功能上跟goland差不多.不过团队的其它开发者基本都是Goland, ...

  2. 单麦克风AI降噪模块及解决方案

    前记   随着以AI为核心的智能设备的广泛发展,语音这个非常重要的入口一直是很多厂商争夺的市场.作为音频采集的前端设备,能采集到的距离远,清晰度高,无噪声的信号是一个非常重要的能力.这样就对音频前端降 ...

  3. MD5算法:密码学中的传奇

    MD5算法起源: MD5(Message Digest Algorithm 5)算法是由MIT的计算机科学家Ronald Rivest于1991年设计的一种消息摘要算法.MD5算法最初被用于提供数据完 ...

  4. 《TencentNCNN系列》 之工作原理简要解析(以LeNet-5为例)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  5. C++ memcpy、memmove

    函数原型: void *memcpy(void *dest, const void* src, size_t count ); void *memmove(void *dest, const void ...

  6. C#的窗体防闪烁解决方案 - 开源研究系列文章

    昨天编码的时候想到了关于无边框窗体的闪烁问题,主要是改变窗体大小的时候会闪烁,默认的窗体没这个问题.而现在无边框窗体的应用比较多,所以就找了度娘,然后结合自己的经验进行了测试,得到了这个例子,简单有效 ...

  7. 记录--h5调用手机摄像头踩坑

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. 背景 一般业务也很少接触摄像头,有也是现成的工具库扫个二维码.难得用一次,记录下踩坑. 2.调用摄像头的方法 2.1. input ...

  8. 【已失效】Xcode GUI 添加 SPM 依赖的时候访问不了 github,无视 git config proxy 配置解决方案

    此 openradar 中提出者指出了原因:Xcode 调用 libgit2 时传入了 GIT_PROXY_NONE,无视了 git config 中的 proxy 配置.作者说用了自己打的 libg ...

  9. 2024-03-23:用go语言,一张桌子上总共有 n 个硬币 栈 。每个栈有 正整数 个带面值的硬币, 每一次操作中,你可以从任意一个栈的 顶部 取出 1 个硬币,从栈中移除它,并放入你的钱包里。

    2024-03-23:用go语言,一张桌子上总共有 n 个硬币 栈 .每个栈有 正整数 个带面值的硬币, 每一次操作中,你可以从任意一个栈的 顶部 取出 1 个硬币,从栈中移除它,并放入你的钱包里. ...

  10. Java AES CBC模式 加密和解密

    import org.apache.tomcat.util.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.s ...