Java的内存机制详解

所属分类: 软件编程 / java 阅读数: 26
收藏 0 赞 0 分享

Java把内存分为两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后(比如,在函数A中调用函数B,在函数B中定义变量a,变量a的作用域只是函数B,在函数B运行以后,变量a会自动被销毁。分配给它的内存会被回收),Java会自动释放掉为该变量分配的内存空间,该内存空间可以立即另做他用。

堆内存用来存放由new创建的内存数组,在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生一个数组或对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就变成了数组或对象的引用变量,以后就可以在程序中使用栈中的变量来访问堆中的数组或者对象,引用变量就相当于为数组或者对象起的一个名字。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其他作用域之外后边释放。而数组和对象本省在堆中分配,即使程序运行到使用new产生的数组或者对象的语句所在的代码块之外,数组和对象本省占据的内存不会被释放。数组和对象在没有引用变量指向它的时候,才变为垃圾,不能再被使用,在随后的一个不确定时间被垃圾回收器收走(释放掉)。这也是Java比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针。

代码实例Demo1:单个对象创建

class Person {
 String name ;
 int age ;
 public void tell() {
  System.out.println("姓名:"+name+",年龄:"+age);
 }
}
public class Demo1 {
 public static void main(String[] args) {
  Person per = new Person() ;
 }
}

在上述程序中实例化了一个对象per,在实例化的过程中需要再内存中开辟空间,这其中就包括栈内存和堆内存,具体的内存分配如下图所示:

 图1-1 对象的实例化过程

我们可以从上图中发现,对象名称per被保存在了栈内存中(更加准确的说法是,在栈内存中保存的是堆内存空间的访问地址),而对象的具体内容,比如属性name和age,被保存在堆内存中。因为per对象只是被实例化,还没有被具体赋值,所以都是默认值。字符串的默认值为null,int的类型的默认值为0。前面已经提到,堆内存空间必须使用new关键字才能开辟。

代码实例Demo2:多个对象创建

class Person {
 String name ;
 int age ;
 public void tell() {
  System.out.println("姓名:"+name+",年龄:"+age);
 }
}
public class Demo2 {
 public static void main(String[] args) {
  Person per1 = new Person() ;
  Person per2 = new Person() ;
  per1.name="张三" ;
  per1.age=30 ;
  per2.age=33 ;
  per1.tell(); 
  per2.tell(); 
 }
}

图1-2 实例化两个对象

关键概念:类跟数组一样,都是属于引用类型,引用类型就是指同一个堆内存可以被多个栈内存指向,下面来看一下引用传递的简单实例。

代码实例Demo3:对象引用传递1

class Person {
 String name ;
 int age ;
 public void tell() {
  System.out.println("姓名:"+name+",年龄:"+age);
 }
}
public class Demo3 {
 public static void main(String[] args) {
  Person per1 = new Person() ;
  Person per2 = per1 ;//-------注意--------
  per1.name="张三" ;
  per1.age=30 ;
  per2.age=33 ;
  per1.tell(); 
  per2.tell(); 
 }
}

程序运行结果为:

从程序的运行结果可以发现,两个对象输出的内容一样,实际上所谓的引用传递,就是将一个堆内存空间的使用权交给多个栈内存空间,每个栈内存空间都可以修改堆内存空间的内容,此程序的内存分配图如下所示:

图1-3 对象引用的传递内存分配

 

图1-3 对象引用的传递内存分配(续)

注意:上述实例中对象per2没有堆内存空间,这是因为对象per2只进行声明操作,也没有进行实例化操作。只是使用new关键字,实例化以后才会有堆内存空间

代码实例Demo4:对象引用传递2

 class Person {
 String name ;
 int age ;
 public void tell() {
  System.out.println("姓名:"+name+",年龄:"+age);
 }
}
public class Demo4 {
 public static void main(String[] args) {
  Person per1 = new Person() ;
  Person per2 = new Person() ;
  per1.name="张三" ;
  per1.age=30 ;
  per2.name="李四" ;
  per2.age=33 ;
  per2=per1 ;//-----注意----
  per1.tell(); 
  per2.tell(); 
 }
}

上述运行程序结果为:

从程序的输出结果可以发现跟Demo3差不多。不过内存分配发生了一些变化,具体如下所示:

图1-4 (垃圾对象)的产生

注意点:

1.Java本身提供垃圾收集机制(Garbage Collection,GC),会不定期释放不用的内存空间,只要对象不用了,就会等待GC释放空间,如上面堆内存中的name="李四";age=33。

2.一个栈内存只能指向一个堆内存空间,如果要想指向其他堆内存空间,则必须先断开已有的指向,才能分配新的指向。

Java中常见的内存区域

在Java中主要存在4块内存空间,这些内存的名称及作用如下:

  1.栈内存空间:保存所有对象的名称。

  2.堆内存空间:保存每个对象的具体属性内容。

  3.全局数据区:保存static类型的属性值。

  4.全局代码区:保存所有的方法定义。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!

更多精彩内容其他人还在看

Collections工具类_动力节点Java学院整理

Collections工具类提供了大量针对Collection/Map的操作。这篇文章主要介绍了Collections工具类_动力节点Java学院整理,需要的朋友可以参考下
收藏 0 赞 0 分享

SpringMVC集成Swagger实例代码

本篇文章主要介绍了SpringMVC集成Swagger实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

十大常见Java String问题_动力节点Java学院整理

本文介绍Java中关于String最常见的10个问题,需要的朋友参考下吧
收藏 0 赞 0 分享

Java微信公众平台开发(13) 微信JSSDK中Config配置

这篇文章主要为大家详细介绍了Java微信公众平台开发第十三步,微信JSSDK中Config配置,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Java实现一个达达租车系统的步骤详解

这篇文章主要给大家介绍了利用Java实现一个达达租车系统的步骤,文中给出了详细的实现思路和示例代码,并在文末给出了完整的源码供大家学习下载,需要的朋友可以参考借鉴,下面来一起看看吧。
收藏 0 赞 0 分享

Java微信公众平台开发(14) 微信web开发者工具使用

这篇文章主要为大家详细介绍了Java微信公众平台开发第十四步,微信web开发者工具的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Spring Boot整合RabbitMQ实例(Topic模式)

Topic Exchange 转发消息主要是根据通配符。接下来通过本文给大家分享Spring Boot整合RabbitMQ实例(Topic模式),需要的朋友参考下吧
收藏 0 赞 0 分享

Java微信公众平台开发(15) 微信JSSDK的使用

这篇文章主要为大家详细介绍了Java微信公众平台开发第十五步,微信JSSDK的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

java多线程的同步方法实例代码

这篇文章主要介绍了 java多线程的同步方法实例代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

spring boot整合RabbitMQ实例详解(Fanout模式)

这篇文章主要介绍了spring boot整合RabbitMQ的实例讲解(Fanout模式),非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多