java 内存分配实例_java内存管理实例讲解
一.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内存管理实例讲解相关推荐
- 【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析
. Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...
- SQL SERVER 内存分配及常见内存问题(1)——简介
原文:SQL SERVER 内存分配及常见内存问题(1)--简介 一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解 ...
- C++内存分配方式、内存错误及其对策
C++内存分配方式.内存错误及其对策 内存分配方式有三种: 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. 在栈上创建.在执 ...
- 静态内存分配与动态内存分配
静态内存分配与动态内存分配 动机 平时看c/c++的书籍时,总会看到一种观点,说是C/C++语言使用的时候动态内存分配是最重要的,使用malloc等函数分配的内存必须要释放,否则及其容易出现内存泄露. ...
- C语言静态内存分配与动态内存分配
C语言中,内存主要分为5个区,分别为栈区.堆区.全局/静态存储区.常量存储区.代码区. 其中代码区存放源程序的二进制代码,其余四个区都存储进程运行过程中需要的存储的变量. 变量的内存分配有两种:静态与 ...
- 【c++内存系列】二、c++动态内存分配和静态内存分配
一.内存的静态分配与动态分配方式 先简单理解静态分配与动态分配: 静态内存分配和动态内存分配比较典型的例子就是数组和链表,数组的长度是预先定义好的,在整个程序中是固定不变的,所以他在内存分配时是以静态 ...
- java double储存原理_Java内存分配原理
Java内存分配与管理是Java的核心技术之一,一般Java在内存分配时会涉及到以下区域: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 ...
- java 常量池 堆_Java 内存分配(堆、栈、常量池)
Java内存分配: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,以及成员方法中的局部变量 ◆堆:存放对象本身(成员变量+成员方法的引用) ◆静态域:存放在对象中用static ...
- java内存区域与内存溢出异常_Java内存区域与内存溢出异常
Java的内存管理是一个老生常谈的问题,虽然Java号称可以自动管理自己的内存,使程序员从内存管理的围墙解放出来,但是一连串的内存泄漏和溢出方面的问题,使得我们不得不去深入了解Java的内存管理机制. ...
最新文章
- spring cloud微服务分布式云架构--hystrix的使用
- python识别latex公式_Python代码转Latex公式,这个开源库用一行代码帮你搞定
- Django 数据库ORM 操作 - 字段的类型和参数
- 爬虫python代码-一则python3的简单爬虫代码
- 一个mui+ajax+php的demo
- Sonic 开源移动端云真机测试平台 - 设备中心接入安卓设备实例演示,Agent端服务部署过程详解
- 继鼎晖夹层完成80亿募集后,鼎晖夹层IDC基金首轮关账15亿
- 迭代器 生成器 装饰器 匿名函数
- python如何训练图片_Python练习第一题,在图片上加入数字
- SpringBoot2 整合 AXIS2 服务端和客户端
- 解决MFC 窗口创建时 争夺焦点的问题
- Python入门--python中的global
- 20200710每日一句
- 微信小程序图片转换成文字_涨知识!这个微信小程序,能将纸上文字转换成电子版...
- Python学习笔记(15)-Python常用模块总结
- HTML5 与 CSS3 jQuery部分知识总结
- 怎样用计算机传输文件,如何在两台电脑之间传输几百G的文件?教你一招
- NLS_LANG与NLS_LANGUAGE的区别
- 如何在计算机桌面上添加小工具,怎么在电脑的桌面小工具里添加便签
- JAVA帮助文档全系列
热门文章
- Oracle用户密码使用特殊符号,例如(AND)、$(Dollar)、#(Pound)、*(Star)等
- python网页提交表单_使用Python中的POST请求通过网站表单上传基本文件
- jar包里java.lang.NoSuchMethodError异常,
- 生成随机位数的UUID
- Feign Client 原理和使用
- 前端制作动画的几种方式(css3,js)
- 删除字符,用外部函数
- jquery 让div滚动条自动滚动到最下面
- [iOS]如何把App打包成ipa文件,然后App上架流程[利用Application Loader]
- Java BIO 聊天程序