Java内存结构对于我们这些初学者来说,学习起来比较困难,正好忙着学习总结,顺便跟大家分享下。
1. Java有几种存储区域?
寄存器
--在CPU内部,开发人员不能通过代码来控制寄存器的分配,有编译器来管理。
堆
--在windows下,栈是向底地址扩展的数据结构,是一块连续的内存的区域,即栈顶的地址和栈的最大容量是系统预先定好的。
--优点:由系统自动分配,速度较快。
--缺点:不够灵活,程序员无法控制。
--存放基本数据类型、开发过程中就创建的对象(而不是运行过程中)。
栈
--是向高地址扩展的数据结构,是不连续的内存区域。
--在堆中,没有堆栈指针,为此也就无法直接从处理器那边获得支持。
--堆的好处是有很大的灵活性。如Java编译器不需要知道从堆里需要分配多少存储区域,也不必知道存储的数据在堆里会存活多长时间。
静态存储区域与常量存储区域
--静态存储区用来存放static类型的变量
--常量存储区用来存放常量类型(final)类型的值,一般在只读存储器中。
非RAM存储
--如流对象,是要发送到另一台机器上。
--持久化的对象,存放在磁盘上。
2. Java内存分配
--基础数据类型直接在栈空间分配。
--方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收。
--引用数据类型,需要用new来创建,既在栈空间分配一个地址空间,又在堆空间分配对象的类变量。
--方法的引用参数,在栈空间分配一个地址空间,并指向堆空间的对象区,当方法调用完后从栈空间回收。
--局部变量new出来时,在栈空间和堆空间中分配空间,当局部变量生命周期结束后,栈空间立即被回收,堆空间区域等待GC回收。
--方法调用时传入的literal参数,先在栈空间分配,在方法调用完成后从栈空间释放。
--字符串常量在DATA区域分配,this在对空间分配
--数组既在栈空间分配数组名称,又在堆空间分配数组实际的大小
3. Java内存模型
Java虚拟机将其管辖的内存大致分三个逻辑部分:方法区、栈、堆。
--方法区是静态分配的,编译器将变量绑定在某个存储位置上,而且这些绑定不会再运行时改变。
常数池,源代码中的命名常量、string常量和static变量保存在方法区。
--Java Stack是一个逻辑概念,特点是后进先出。一个栈的空间可能是连续的,也可能是不连续的。
最典型的stack应用是方法的调用,java虚拟机每调用一次方法就创建一个方法帧(frame),退出时则对应的方法帧被弹出。栈中存储的数据也是运行时确定的。(弹匣)
--Java堆分配 意味着以随意的顺序,在运行时进行存储空间分配和收回的内存管理模型。
堆中存储的数据常常是大小、数量和生命期在编译时无法确定的。java对象的内存总是在heao中分配。
二、Java垃圾回收机制(GC)
1. JVM运行环境中垃圾对象的定义
一个对象创建后被放置在JVM的堆内存中,当永远不再引用这个对象时,它将被JVM在堆内存中回收。或当对象在JVM运行空间中无法通过根集合(root set)到达时,这个对象就被称为垃圾对象。
2. 堆内存
在JVM启动时被创建;堆内存中所存储的对象可以被JVM自动回收,不能通过其他外部手段回收。
堆内存可分为两个区域:新对象区和老对象区
--新对象区可分为三个小区:Eden区、From区、To区
3. JVM中对象的生命周期
创建阶段
--为对象分配存储空间
--开始构造对象
--递归调用其超类的构造方法
--进行对象实例初始化与变量初始化
--执行构造方法体
应用阶段
--特征:系统至少维护着对象的一个强引用;所有对该对象引用强引用(除非显示声明为其他引用)
不可视阶段
--如果一个对象已使用完,并且在其可视区域不再使用,应该主动将其设置为null,即obj=null;这样可以帮助JVM及时发现这个垃圾对象,并且可以及时地回收该对象所占用的系统资源。
4. finalize
finalize()方法常称之为终止器
protected void finalize(){
// finalization code here
}
对象即将被销毁时,有时需要做一些善后工作,可以把这些操作写在finalize()方法里。
Java终止器却是在对象被销毁时调用。一旦垃圾收集器准备好释放无用对象占用的存储空间,它首先调用那些对象的finalize()方法,然后才真正回收对象的内存。而被丢弃的对象何时被销毁,应用是无法获知的。大多数场合,被丢弃对象在应用终止或仍未销毁。到程序结束的时候,并非所有收尾模块都会得到调用。
|
|