最近,学校开始了关于操作系统方面的课程设计,刚在网上看到了一篇不错的博客关于java中的内存分配问题。参考博客简单说说java的内存分配。
首先要知道的是Java程序运行在JVM(Java Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁(我自己觉得JVM就相当于操作系统),JVM实现了Java的平台无关性,由此可见JVM的重要性。所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提。
1.Java程序运行的内存:
寄存器:JVM内部虚拟寄存器,存取速度非常快,程序不可控制。
栈:保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用(指针);3也可以用来保存加载方法时的帧。
堆:用来存放动态产生的数据,比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量(对象的属性),并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。
常量池:JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中。
代码段:用来存放从硬盘上读取的源程序代码。
数据段:用来存放static定义的静态成员。
图示:
2.调用过程:
(1)
1.JVM自动寻找main方法,执行第一句代码,创建一个Test类的实例,在栈中分配一块内存,存放一个指向堆区对象的指针110925。
2.创建一个int型的变量date,由于是基本类型,直接在栈中存放date对应的值9。
3.创建两个BirthDate类的实例d1、d2,在栈中分别存放了对应的指针指向各自的对象。他们在实例化时调用了有参数的构造方法,因此对象中有自定义初始值。
(2)
调用test对象的change1方法,并且以date为参数。JVM读到这段代码时,检测到i是局部变量,因此会把i放在栈中,并且把date的值赋给i。
(3)
调用change1,将1234赋给i.
(4)
change1方法执行完毕,立即释放局部变量i所占用的栈空间。
(5)
调用test对象的change2方法,以实例d1为参数。JVM检测到change2方法中的b参数为局部变量,立即加入到栈中,由于是引用类型的变量,所以b中保存的是d1中的指针,此时b和d1指向同一个堆中的对象。在b和d1之间传递是指针。
(6)
change2方法中又实例化了一个BirthDate对象,并且赋给b。在内部执行过程是:在堆区new了一个对象,并且把该对象的指针保存在栈中的b对应空间,此时实例b不再指向实例d1所指向的对象,但是实例d1所指向的对象并无变化,这样无法对d1造成任何影响。
(7)
change2方法执行完毕,立即释放局部引用变量b所占的栈空间,注意只是释放了栈空间,堆空间要等待自动回收。
(8)
调用test实例的change3方法,以实例d2为参数。同理,JVM会在栈中为局部引用变量b分配空间,并且把d2中的指针存放在b中,此时d2和b指向同一个对象。再调用实例b的setDay方法,其实就是调用d2指向的对象的setDay方法。
(9)
调用实例b的setDay方法会影响d2,因为二者指向的是同一个对象。
(10)
change3方法执行完毕,立即释放局部引用变量b.
3.小结:
1.分清什么是实例什么是对象。Class a= new Class();此时a叫实例,而不能说a是对象。实例在栈中,对象在堆中,操作实例实际上是通过实例的指针间接操作对象。多个实例可以指向同一个对象。
2.栈中的数据和堆中的数据销毁并不是同步的。方法一旦结束,栈中的局部变量立即销毁,但是堆中对象不一定销毁。因为可能有其他变量也指向了这个对象,直到栈中没有变量指向堆中的对象时,它才销毁,而且还不是马上销毁,要等垃圾回收扫描时才可以被销毁。
3.以上的栈、堆、代码段、数据段等等都是相对于应用程序而言的。每一个应用程序都对应唯一的一个JVM实例,每一个JVM实例都有自己的内存区域,互不影响。并且这些内存区域是所有线程共享的。这里提到的栈和堆都是整体上的概念,这些堆栈还可以细分。
4.类的成员变量在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中)。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存。
以上分析只涉及了栈和堆,还有一个非常重要的内存区域:常量池,这个地方往往出现一些莫名其妙的问题。常量池是干嘛的上边已经说明了,也没必要理解多么深刻,只要记住它维护了一个已加载类的常量就可以了。接下来结合一些例子说明常量池的特性。
5.Java 提供两种不同的类型:引用类型和基本类型(或内置类型)。Int是java的基本数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。
基本类型封装类
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double .
相关推荐
Java内存分配是Java编程中非常重要的概念,它涉及到程序运行时的数据存储和管理。Java程序在JVM(Java Virtual Machine,Java虚拟机)上运行,JVM作为一个平台无关的执行环境,负责Java程序的内存管理和执行。理解...
### Java中堆内存与栈内存分配浅析 #### 一、引言 在Java编程语言中,内存管理是一项至关重要的技术。程序运行时所使用的内存主要分为两类:堆内存(Heap Memory)和栈内存(Stack Memory)。理解这两种内存类型的...
所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提。l.寄存器:JVM内部虚拟寄存器,存取速度非常快,程序不可控制。2.栈:保存局部变量的值,包括:1.用来保存基
Java中的抽象类(abstract class)和接口(interface)都是用于创建抽象化模型的重要工具,它们在面向对象编程中扮演着核心角色。这两种机制都允许我们定义一组方法的签名,但不提供具体实现,从而实现“设计契约”...
本文详细解析了Java中对象创建的整个流程,涵盖了类信息存储、对象引用、对象实体的内存分配以及实例化过程中方法的调用。 首先,Java的内存结构是理解对象创建的基础。JVM(Java虚拟机)为每一个运行中的Java应用...
### 浅析Java引用类型和方法参数传递 #### 一、引言 在Java编程语言中,理解数据类型的处理方式对于编写高效、可维护的代码至关重要。本文将深入探讨Java中的引用类型及其如何影响方法参数的传递机制。通过具体实例...
"浅析java之对象数组" 本文主要探讨Java中对象数组的知识点,着重介绍基本数据类型数组和对象数组的声明、创建和使用。文章首先介绍了Java的基本概念和特点,然后详细探讨了一维数组的声明和使用,包括基本数据类型...
在Java编程语言中,对象的创建是程序运行的基础,它涉及到类的实例化、内存分配以及构造函数的调用等多个步骤。本篇文章将深入探讨Java中对象创建的全过程,帮助开发者理解这一核心概念。 首先,我们需要了解的是...
Java对象的内存分配在堆上,而C/C++中的动态内存管理通常涉及栈和堆。在Java中,创建对象时,内存分配由JVM自动完成,而C/C++则需要程序员手动使用`new`或`malloc`等关键字。Java的内存管理更为自动化,但牺牲了对...
1. **Java内存模型**:Java内存分为堆内存和栈内存,对象分配在堆中,局部变量存储在栈上。Android应用基于Dalvik/ART虚拟机,其内存管理机制与标准Java有所不同。 2. **Android内存结构**:Android系统有Dalvik堆...
- **Android Studio Profiler**:提供实时内存监控,可以查看内存分配、内存泄漏检测等功能。 - **MAT (Memory Analyzer Tool)**:Eclipse插件,用于分析Hprof文件,找出内存泄漏。 - **LeakCanary**:自动检测...
6. **使用内存分析工具**:Android Studio提供了强大的内存分析工具,如Memory Profiler,可以帮助开发者检测内存泄漏、分析内存分配和GC行为。通过这些工具,可以定位并修复内存问题。 7. **优化代码结构**:良好...
Android系统使用Java虚拟机(Dalvik或ART)进行内存分配和管理,但如果不妥善处理,很容易引发内存溢出问题,导致应用崩溃或者性能下降。本资料"安卓Android源码——防止内存溢出浅析"将深入探讨如何在Android源码...
例如,Java的自动内存管理机制减少了程序员管理内存分配和回收的负担,提高了开发效率,同时降低了程序出错的可能性。 Java语言的扩展性强,是指它在运行时能够动态地加载类,这意味着程序可以在运行时扩展自己的...
1. 分配内存:Java虚拟机(JVM)在堆内存中为新对象分配所需的空间。这个过程包括为对象的所有字段分配内存。 2. 初始化:接下来,对对象的成员变量进行默认初始化。例如,基本类型变量会被赋予默认值,引用类型...