Java变量,内存 ,垃圾回收

目录

内存和变量

垃圾回收器GC

数据结构


转载和整合:https://blog.csdn.net/csdnliuxin123524/article/details/74888800


内存和变量

java把内存分为两部分,一部分栈内存,一部分是堆内存,在函数中定义的一些基本类型的变量和对象都是在栈内存中分配的

由java基本类型byte,int,short,long float,double,boolean,char 这八种定义的变量,在java为了追求速度是直接在栈中为期分配内存空间的,不是类的引用.在栈中有个"数据共享"的特性,比如,定义一个int a=3,栈会定义一个变量为a的引用,如果栈中一开始没有3,则栈会开辟一个存放字面值为3的地址.当再定义一个int b=3,栈会创建变量为b的引用,但是栈中已经有了一个字面值为3的地址,所以会出现a和b同时指向3的情况,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

堆内存是用来存储new创建的对象和数组,其内存分配是由java虚拟机的自动垃圾回收器管理,在堆中产生了一个数组或对象之后,可以在栈中定义一个特殊的变量,让这个变量的值是数组或对象在堆内存的首地址,栈的这个变量变成了堆中的数组或对象的引用变量.以后就可以使用栈的引用变量来访问堆的数组或对象。引用变量在运行到其作用域之外便被释放,堆中的数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。

这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

1、类变量(static修饰的变量):在程序加载时系统就为它在堆中开辟了内存,堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期--一直持续到整个"系统"关闭

2、实例变量:当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量(比如说类实例),然后根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的"物理位置"。 实例变量的生命周期--当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存

3、局部变量:局部变量,由声明在某方法,或某代码段里(比如for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放

常量池:存放字符串常量和基本类型常量,为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享


垃圾回收器GC

垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制

标记清除算法:

1. 标记:垃圾收集器会从 根(root) 引用开始,标记它到达的所有对象

2. 清除:如果一个对象被判定为是可以回收的对象,那么这个对象就被放在一个 finalization queue(回收队列)中,并在稍后会由一个虚拟机自动建立的、低优先级的 finalizer 线程去执行它。

3. 整理:将存活的对象整理在一起,防止堆碎片化,防止大对象在堆中由于堆空间的不连续性而无法分配的情况。

根节点如何判断存活对象?算法是通过一系列的根节点,向下搜索,搜索路径叫做 引用链,当对象和root没有任何引用链相连,此对象不可用。

红色部分表示,对象作用域,当跳出作用域,比如跳出子函数后,局部变量就不可达了!

软可达表示 有用但没必要,在OutOfMemoryError出现前,堆会保留他们,弱可达随时会被回收。


数据结构

栈堆是先进后出,可以使用链表或数组表示

队列是先进先出,只能在队尾添加数据,队头删除数据,但是,可以查看队头和队尾的数据,还有双端队列,在两端都可以插入和删除,可以用链表和数组表示。

数组:连续的内存空间保存数据,

链表:是在非连续的内存单元中保存数据。


 

基础类型的传参,int a=4; f(a);为a在栈分配区域 地址指向4, f(a)传递的不是引用 而是4

String属于引用传递,但是它很特殊,在参数传递时它是重新new了一个String,子函数的参数改变,不会改变原本的string

方式一:String a = “aaa” ; 在常量池中找到“aaa"地址给a这个对象,找不到就在常量池存一个”aaa"

方式二:String b = new String(“aaa”);在堆中为b开辟空间,为b在常量池开辟空间,放入“aaa",相当于创建了两个对象

其他引用传递,传递的是引用地址,会更改实际的值。Dog dog=new Dog();f(dog)

当比较包装类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==

常量池的使用:对于基础类型的变量和常量:变量和引用存储在栈中,常量存储在常量池中。a="aaa"是字符串常量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值