设为首页 加入收藏

TOP

Java 虚拟机 2:Java 内存区域及对象(一)
2018-03-27 08:59:46 】 浏览:324
Tags:Java 虚拟 内存 区域 对象

几个计算机的概念

为以后写文章考虑,也为巩固自己的知识和一些基本概念,这里要理清楚几个计算机中的概念。

1、计算机存储单位

从小到大依次为位Bit字节Byte千字节KB兆M千兆GBTB,相邻单位之间都是1024倍,1024为2的10次方,即:

  • 1Byte = 8bit
  • 1K = 1024Byte
  • 1M = 1024K
  • 1G = 1024M
  • 1T = 1024G

2、计算机存储元件

寄存器:中央处理器CPU的一部分,是计算机中读写速度最快的存储元件,但是容量很少

内存:属于独立的一个部件,是和CPU沟通的桥梁,用于存放CPU中的运算数据以及与外部存储器交换的数据。尽管在今天,对内存的读写速度已经很快了,但是由于寄存器是在CPU上的,所以对于内存的读写速度和对于寄存器的读写速度上还是有几个数量级的差距。但是没办法,对于内存的读写I/O操作是很难消除的,寄存器数量有限,不可能通过寄存器来完成所有的运算任务

3、内核空间和用户空间

连接内存和寄存器的是地址总线,地址总线的宽度影响了物理地址的索引范围,因为总线宽度决定了处理器一次可以从寄存器或内存中获取多少个Bit,同时也决定了处理器最大可以寻址的地址空间。比如32位CPU的系统,可寻址范围为0×00000000~0xFFFFFFFF,即232=4294967296个内存位置,每个内存位置1个字节,即32位CPU系统可以有4GB的内存空间。不过应用程序是不可以完全使用这些地址空间的,因为这些地址空间被划分为了内核空间和用户空间,程序只能使用用户空间的内存。内核空间主要是指操作系统运行时所使用的用于程序调度、虚拟内存的使用或者链接硬件资源的程序逻辑。区分内核空间和用户空间的目的主要是从系统的稳定性的角度考虑的。Windows 32操作系统默认内核空间和用户空间的比例是1:1,即2G内核空间、2G内存空间,32位Linux系统中默认比例则是1:3,即1G内核空间,3G内存空间。

4、字长

CPU的主要技术指标之一,指的是CPU一次能并行处理二进制的位数(Bit)。通常称处理字长为8位数据的CPU为8位CPU,32位CPU就是在同一时间内处理字长为32位的二进制数据。不过目前虽然CPU大多是64位的,但还是以32位字长运行

前言

说到Java内存区域,可能很多人第一反应是“堆栈”。首先堆栈不是一个概念,而是两个概念,堆和栈是两块不同的内存区域,简单理解的话,堆是用来存放对象而栈是用来执行程序的。其次,堆内存和栈内存的这种划分方式比较粗糙,这种划分方式只能说明大多数程序员最关注的、与对象内存分配关系最密切的内存区域是这两块,Java内存区域的划分实际上远比这复杂。对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去配对delete/free代码,不容易出现内存泄露和内存溢出问题。但是,也正是因为Java把内存控制权交给了虚拟机,一旦出现内存泄露和内存溢出的问题,就难以排查,因此一个好的Java程序员应该去了解虚拟机的内存区域以及会引起内存泄露和内存溢出的场景。

运行时数据区域

Java虚拟机(JVM)内部定义了程序在运行时需要使用到的内存区域,从http://images.blogjava.net/blogjava_net/nkjava/jvmstructure.png拷贝一张图下来

之所以要划分这么多区域出来是因为这些区域都有自己的用途,以及创建和销毁的时间。有些区域随着虚拟机进程的启动而存在,有的区域则依赖用户线程的启动和结束而销毁和建立。图中绿色部分就是所有线程之间共享的内存区域,而白色部分则是线程运行时独有的数据区域,从这个分类角度来看一下这几个数据区。

1、线程独有的内存区域

(1)PROGRAM COUNTER REGISTER,程序计数器

这块内存区域很小,它是当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令。Java方法这个计数器才有值,如果执行的是一个Native方法,那这个计数器是空的。

(2)JAVA STACK,虚拟机栈

生命周期和线程相同。每个方法执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。栈的大小和具体JVM的实现有关,通常在256K~756K之间。

(3)NATIVE METHOD STACK,方法栈

和虚拟机栈起的作用一样,只不过方法栈为虚拟机使用到的Native方法服务。虚拟机规范并没有对这个区域有什么强制规定,因此我们使用的HotSpot虚拟机,就干脆没有这块区域了,它和虚拟机栈是一起的。

2、线程间共享的内存区域

(1)HEAP,堆

大多数应用,堆都是Java虚拟机所管理的内存中最大的一块,它在虚拟机启动时创建,此内存唯一的目的就是存放对象实例。由于现在垃圾收集器采用的基本都是分代收集算法,所以堆还可以细分为新生代和老年代,再细致一点还有Eden区、From Survivior区、To Survivor区,这个后面都会讲到的。

(2)METHOD AREA,方法区

这块区域用于存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,虚拟机规范是把这块区域描述为堆的一个逻辑部分的,但实际它应该是要和堆区分开的。从上面提到的分代收集算法的角度看,HotSpot中,方法区≈永久代。不过JDK 7之后,我们使用的HotSpot应该就没有永久代这个概念了,会采用Native Memory来实现方法区的规划了。

(3)RUNTIME CONSTANT POOL,运行时常量池

上面的图中没有画出来,因为它是方法区的一部分。Class文件中除了有类的版本信息、字段、方法、接口等描述信息外,还有一项信息就是常量池,用于存放编译期间生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中,另外翻译出来的直接引用也会存储在这个区域中。这个区域另外一个特点就是动态性,Java并不要求常量就一定要在编译期间才能产生,运行期间也可以在这个区域放入新的内容,String.intern()方法就是这个特性的应用。

3、直接内存

想想还是把这块加上。直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但是这部分内存也被频繁地使用,而且也可能导致内存溢出问题。JDK1.4中新增加了NIO,引入了一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。显然,本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,肯定还是会受到本机总内存(包括RAM、SWAP区)大小以及处理器寻址空间的限制。

对象创建

Java是一门面向对象的语言,Java程序运行过程中无时无刻都有对象被创建出来。在语言层面上,创建对象(克隆、反序列化)就是一个new关键字而已,但是

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇在 Java 8 中避免 Null 检查 下一篇Java虚拟机 5:Java垃圾回收(GC..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目