Java程序运行在JVM(Java  Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可 见JVM的重要性。所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提。

        一个完整的Java程序运行过程会涉及以下内存区域:

寄存器:JVM内部虚拟寄存器,存取速度非常快,程序不可控制。

栈:保存局部变量的值,包括:a.用来保存基本数据类型的值;b.保存类的实例,即堆区对象的引用(指针)。也可以用来保存加载方法时的帧。

堆:用来存放动态产生的数据,比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。

常量池:JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用(1)。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中

代码段:用来存放从硬盘上读取的源程序代码。

数据段:用来存放static定义的静态成员,一直占用内存。

下图表示内存分配图:

 

 

对于java 和内存之间,有如下几点需要注意:

   1.一个Java文件,只要有main入口方法,我们就认为这是一个Java程序,可以单独编译运行。

   2.无论是普通类型的变量还是引用类型的变量(俗称实例),都可以作为局部变量,他们都可以出现在栈中。只不过普通类型的变量在栈中直接保存它所对应的值,而引 用类型的变量保存的是一个指向堆区的指针,通过这个指针,就可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量 要在栈区和堆区各占一块内存。

  3.栈中的数据和堆中的数据销毁并不是同步的。方法一旦结束,栈中的局部变量立即销毁,但是堆中对象不一定销毁。因为可能有其他变量也指向了这个对象,直到栈中没有变量指向堆中的对象时,它才销毁,而且还不是马上销毁,要等垃圾回收扫描时才可以被销毁。

   4.每一个应用程序都对应唯一的一个JVM实例,每一个JVM实例都有自己的内存区域,互不影响。并且这些内存区域是所有线程共享的。这里提到的栈和堆都是整体上的概念,这些堆栈还可以细分。以上的栈、堆、代码段、数据段等等都是相对于应用程序而言的。

  5 .类的成员变量在位于数据段中一直占用内存。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存。

     补充:分清什么是实例什么是对象。Class a= new Class();此时a叫实例,而不能说a是对象。实例在栈中,对象在堆中,操作实例实际上是通过实例的指针间接操作对象。多个实例可以指向同一个对象。

  以上分析只涉及了栈和堆,还有一个非常重要的内存区域:常量池,这个地方往往出现一些莫名其妙的问题。常量池是干嘛的上边已经说明了,也没必要理解多么深刻,只要记住它维护了一个已加载类的常量就可以了。一下是常量池的几个注意点。

   1.以上提到的几种基本类型包装类均实现了常量池技术,但他们维护的常量仅仅是【-128至127】这个范围内的常量,如果常量值超过这个范围,就会从堆中创建对象,不再从常量池中取。比如,把上边例子改成Integer i1 = 400; Integer i2 = 400;,很明显超过了127,无法从常量池获取常量,就要从堆中new新的Integer对象,这时i1和i2就不相等了。

  2.String类型也实现了常量池技术,但是稍微有点不同。String型是先检测常量池中有没有对应字符串,如果有,则取出来;如果没有,则把当前的添加进去。

文章引用处:Java内存分配全面浅析:http://blog.csdn.net/yangyuankp/article/details/7651251

最新文章

  1. 【CentOS】LAMP相关2
  2. jqgrid
  3. IOS系统概述与层次
  4. 移动端压缩并ajax上传图片解决方案
  5. Hadoop.2.x_简单的测试文件读取与上传
  6. 重命名Oracle数据库的表空间(Renaming a Tablespace)
  7. 使用T4为数据库自动生成实体类
  8. 被mysql中的wait_timeout坑了
  9. Android Training精要(五)讀取Bitmap對象實際的尺寸和類型
  10. python中并行遍历:zip和map-转
  11. CMD打开远程并使用空白密码远程登录
  12. python Aspscheduler 定时任务框架使用
  13. 提醒录入BOM更改原因
  14. Oracle中四种循环(GOTO、For、While、Loop)
  15. 工具类 util.Date 日期类
  16. MySQL数据连表查询思路
  17. Mac 系统占用100g的解决办法
  18. Double.parseDouble(String s)
  19. win10企业版2016长期服务版本激活
  20. centos7下安装docker(13.2容器数据共享)

热门文章

  1. 百万年薪python之路 -- 基本数据类型
  2. Ubuntu18.04 安装PGSQL
  3. 史上最详细的IDEA优雅整合Maven+SSM框架(详细思路+附带源码)
  4. JVM(5) 类加载机制
  5. 【原创】怎样才能写出优雅的 Java 代码?这篇文章告诉你答案!
  6. linux文本编辑器教学
  7. Okhttp 请求流程梳理
  8. Alibaba 镜像
  9. NOIP模拟 34
  10. day 2 下午 骑士 基环树+树形DP