一.java虚拟机运行时内存分配图

二.栈 堆 方法区简介

1.栈

1. 每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)

2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)

3. 栈属于线程私有,不能实现线程间的共享!

4. 栈的存储特性是“先进后出,后进先出”

5. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!

2. 堆

1. 堆用于存储创建好的对象和数组(数组也是对象)

2. JVM只有一个堆,被所有线程共享

3. 堆是一个不连续的内存空间,分配灵活,速度慢!

3.方法区

1. JVM只有一个方法区,被所有线程共享!

3. 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)

三.实例讲解

1.代码

class Point {

private double x;

private double y;

Point(double x1, double y1) {

x = x1;

y = y1;

}

public double getX() { return x; }

public double getY() { return y; }

public void setX(double i) { x = i; }

public void setY(double i) { y = i; }

}

class Circle {

private Point o;

private double radius;

Circle(Point p, double r) {

o = p;

radius = r;

}

public void setO(double x, double y) {

o.setX(x);

o.setY(y);

}

public Point getO() { return o; }

public double getRadius() { return radius; }

public void setRadius(double r) { radius = r; }

public double area() { return 3.14 * radius * radius; }

Circle increaseRadius() {

radius++;

return this;

}

}

public class TestCircle {

public static void main(String args[]) {

Circle c1 = new Circle(new Point(1.0, 2.0), 2.0);

System.out.println("c1:" + c1.getO().getX());

c1.setO(5, 6);

System.out.println(c1.increaseRadius().increaseRadius().area());

}

}

2. 构造函数 Circle c1 = new Circle(new Point(1.0,2.0), 2.0);

2.1 Circle c1

首先在栈内创建一个c1引用,指向地址不详

2.2 new Point(1.0,2.0)

在堆内创建一个Point对象 ,开始时Point内的变量X Y皆为0,

在栈内创建x1,y1,然后将其赋值给Point的x y,构造完成时内存分配如图

构造函数运行完成后,栈内x1,y1空间立刻释放

2.3 在堆内创建Circle对象 new Circle(new Point(1.0,2.0), 2.0)

同样,Circle对象刚创建时引用类型值为null,基础变量值为0,然后进入构造函数,在栈内创建一个指向刚才创建的Point对象的P和值为2.0的r,

然后用这两个元素初始化Circle内元素,使o指向Point,radius值变为2.0

构造函数完成后,栈内的r和p立刻释放

最后将c1指向Circle对象 Circle c1 = new Circle(new Point(1.0,2.0), 2.0);

3. c1.getO().getX()

首先调用geto获得c1所指向的Point,在栈中创建一个引用指向O引用

然后调用getX(),返回其X值,在栈内创建一临时对象用于存储X值

打印完成后,临时对象会被清理

4. c1.setO(5,6);

经过前面的学习,相信这个就很简单了,

在内存中创建临时变量x=5.0,y=6.0,然后通过赋值,改变c1内Point对象的值,SetO()结束后临时变量被清理.

5. c1.increaseRadius().increaseRadius().area() 关于this

首先c1调用increaseRadius()方法,返回一个Circle类的临时引用存储在栈内,指向c1对象,使radius变量+1.然后在通过这个临时引用再次调用increaseRadius()方法,使radius+1,再返回一个临时引用压栈,最后通过这个临时变量调用area()方法获取c1的增大半径后的面积.语句完成后两个栈内临时变量立刻被清理

四.static变量的内存分配

1.代码

class Cat {

public static int num = 0;

String name;

Cat(String name) {

this.name = name;

++num;

}

}

public class Main {

public static void main(String[] args) {

Cat c1 = new Cat("mimi");

Cat c2 = new Cat("miao");

System.out.println(Cat.num);

}

}

2.所有的字符串和static类型的静态成员变量都会预先加载于方法区内

所以上述代码执行时,内存分布如图,可以认为堆内c1,c2各有一引用指向方法区内对应元素

多态(动态绑定的内存分配)

1.代码

class Animal {

public String name;

Animal(String name) { this.name = name; }

void enjoy() { System.out.println("叫声"); }

}

class Dog extends Animal {

public String furName; //毛皮颜色

Dog(String name,String furName) { super(name); this.furName=furName;}

@Override

void enjoy() { System.out.println("汪汪汪"); }

}

class Cat extends Animal {

Cat(String name) { super(name); }

@Override

void enjoy() { System.out.println("miao"); }

}

class lady {

public String name;

public Animal pet;

lady(String name, Animal pet) {

this.name = name;

this.pet = pet;

}

void enjoy() { this.pet.enjoy(); }

void replace_pet(Animal pet) { this.pet = pet; }

}

public class Main {

public static void main(String[] args) {

Dog dog = new Dog("小黄","yellow");

lady w1 = new lady("张不悔", dog);

w1.pet.enjoy();

Cat cat = new Cat("大白","white");

lady w2=new lady("刘静",cat);

w2.pet.enjoy();

}

}

2.运行时,内存分布大致如图

在实际运行时,Lady内部的pet虽然是animal类型的引用,但是其指向的堆内存空间对象是一个完整的Dog对象,注意类内方法并不在堆内存储,类内方法存储在方法区内,堆中类对象只存储指向此方法的一个指针,因而打印出的enjoy结果是"汪汪",而不是"叫声".

但是因为pet类型是Animal,所以通过pet引用只能访问Animal类拥有的方法和变量,比如w1.pet.furname是错误的.因为pet引用并不知道他所引用的对象究竟是dog还是cat,只能判断出其至少是个Animal对象.

需要注意的是,栈内元素在使用完成后会立刻被清理,但是堆内创建的对象并不会立刻消失,而是在垃圾回收器启动回收后才会消失,而为了性能考虑,在内存充沛时,垃圾回收器并不会经常运行.所以可能某个元素已经空置了很久但是仍未被回收.

class Point {

int x, y;

Point(int _x, int _y) {

x = _x;

y = _y;

} //_x,_y在构造函数运行完成后会立刻消失

}

public class Main {

public static void main(String[] args) {

Point p1 = new Point(1, 2);

Point p2 = new Point(2, 3);

p1 = p2; //p1之前所指向的Point对象已经成为空置垃圾,但是不会被立刻回收

}

}

java 内存分配实例_java内存管理实例讲解相关推荐

  1. 【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析

    . Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...

  2. SQL SERVER 内存分配及常见内存问题(1)——简介

    原文:SQL SERVER 内存分配及常见内存问题(1)--简介 一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解 ...

  3. C++内存分配方式、内存错误及其对策

    C++内存分配方式.内存错误及其对策 内存分配方式有三种: 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. 在栈上创建.在执 ...

  4. 静态内存分配与动态内存分配

    静态内存分配与动态内存分配 动机 平时看c/c++的书籍时,总会看到一种观点,说是C/C++语言使用的时候动态内存分配是最重要的,使用malloc等函数分配的内存必须要释放,否则及其容易出现内存泄露. ...

  5. C语言静态内存分配与动态内存分配

    C语言中,内存主要分为5个区,分别为栈区.堆区.全局/静态存储区.常量存储区.代码区. 其中代码区存放源程序的二进制代码,其余四个区都存储进程运行过程中需要的存储的变量. 变量的内存分配有两种:静态与 ...

  6. 【c++内存系列】二、c++动态内存分配和静态内存分配

    一.内存的静态分配与动态分配方式 先简单理解静态分配与动态分配: 静态内存分配和动态内存分配比较典型的例子就是数组和链表,数组的长度是预先定义好的,在整个程序中是固定不变的,所以他在内存分配时是以静态 ...

  7. java double储存原理_Java内存分配原理

    Java内存分配与管理是Java的核心技术之一,一般Java在内存分配时会涉及到以下区域: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 ...

  8. java 常量池 堆_Java 内存分配(堆、栈、常量池)

    Java内存分配: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,以及成员方法中的局部变量 ◆堆:存放对象本身(成员变量+成员方法的引用) ◆静态域:存放在对象中用static ...

  9. java内存区域与内存溢出异常_Java内存区域与内存溢出异常

    Java的内存管理是一个老生常谈的问题,虽然Java号称可以自动管理自己的内存,使程序员从内存管理的围墙解放出来,但是一连串的内存泄漏和溢出方面的问题,使得我们不得不去深入了解Java的内存管理机制. ...

最新文章

  1. spring cloud微服务分布式云架构--hystrix的使用
  2. python识别latex公式_Python代码转Latex公式,这个开源库用一行代码帮你搞定
  3. Django 数据库ORM 操作 - 字段的类型和参数
  4. 爬虫python代码-一则python3的简单爬虫代码
  5. 一个mui+ajax+php的demo
  6. Sonic 开源移动端云真机测试平台 - 设备中心接入安卓设备实例演示,Agent端服务部署过程详解
  7. 继鼎晖夹层完成80亿募集后,鼎晖夹层IDC基金首轮关账15亿
  8. 迭代器 生成器 装饰器 匿名函数
  9. python如何训练图片_Python练习第一题,在图片上加入数字
  10. SpringBoot2 整合 AXIS2 服务端和客户端
  11. 解决MFC 窗口创建时 争夺焦点的问题
  12. Python入门--python中的global
  13. 20200710每日一句
  14. 微信小程序图片转换成文字_涨知识!这个微信小程序,能将纸上文字转换成电子版...
  15. Python学习笔记(15)-Python常用模块总结
  16. HTML5 与 CSS3 jQuery部分知识总结
  17. 怎样用计算机传输文件,如何在两台电脑之间传输几百G的文件?教你一招
  18. NLS_LANG与NLS_LANGUAGE的区别
  19. 如何在计算机桌面上添加小工具,怎么在电脑的桌面小工具里添加便签
  20. JAVA帮助文档全系列

热门文章

  1. Oracle用户密码使用特殊符号,例如(AND)、$(Dollar)、#(Pound)、*(Star)等
  2. python网页提交表单_使用Python中的POST请求通过网站表单上传基本文件
  3. jar包里java.lang.NoSuchMethodError异常,
  4. 生成随机位数的UUID
  5. Feign Client 原理和使用
  6. 前端制作动画的几种方式(css3,js)
  7. 删除字符,用外部函数
  8. jquery 让div滚动条自动滚动到最下面
  9. [iOS]如何把App打包成ipa文件,然后App上架流程[利用Application Loader]
  10. Java BIO 聊天程序