Java虚拟机中,数据装型及其运算都是由Java虚拟机规范严格定义的。数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。
Java定义了8种基本数值类型:byte、short、int、long、char、float、double和boolean。
Java定义的引用类型包括:类类型,接口类型和数组。
java语言中的所有基本类型同样也都是Java虚拟机中的基本装型。但是boolean有点特別,虽然Java虚拟机也把boolean看做基本类型。但是指令集对boolean只有很有限的支持, 当编译器把Java源码编译为字节码时,它会用int或byte来表示boolean。在Java虚拟机中, false是由整数零来表示的,所有非零整数部表示true。涉及boolean值的操作则会使用int。另外, boolean数组是当做byte数组来访问的,但是在“堆”区,它也可以被表示为位域。
除了boolean以外, Java语言中的基本类型构成了Java虚拟机中的数值装型. 虚独机中的数值类型分为两种:整数美型和浮点数类型。和Java语言一样, java虚拟机的基本类型的值域在任何地方都是一致的,比如,不管底层的主机平台是什么. 一个long在任何虚拟机中总是一个64位二进制补码表示的有符号整数。
Java虚拟机中还有一个只在内部使用的基本类型: returnAddress,它返回当前调用函数返回的地址,Java程序员不能使用这个类型。这个基本类型被用来实现Java程序中的finally子句。
Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
8种基本数据类型所对应的包装类型为:
Byte、Short、Integer、Long、Character、Float、Double和Boolean
在JVM虚拟机中所占位数与字节数如下:
类型 | 位数 | 字节数 |
byte | 8 | 1 |
short | 16 | 2 |
int | 32 | 4 |
long | 64 | 8 |
float | 32 | 4 |
double | 64 | 8 |
char | 16 | 2 |
Java虚拟机的引用类型被统称为“引用”(reference),有三种引用装型:类类型,接口类型, 以及数组类型, 它们的值都是对动态创建对象的引用 。 类类型的值是对类实例的引用;数组类型的值是对数组对象的引用, 在Java虚拟机中, 数组是个真正的对象, 而接口类型的值, 则是对实现了该接口的某个类实例的引用 。 还有一种特殊的引用值是null , 它表示该引用变量投有引用任何对象。
Java对象的大小
基本数据的类型的大小是固定的,这里就不多说了。对于非基本类型的Java对象,其大小就值得商榷。在Java中,一个空Object对象的大小是8byte,这个大小只是保存堆中一个没有任何属性的对象的大小,看下面语句:
Object ob = new Object();
这样在程序中完成了一个Java对象的声明,它所占的空间为:4byte+8byte。4byte是Java栈中保存引用的所需要的空间。而那8byte则是Java堆中对象的信息。因为所有的Java非基本类型的对象都需要默认继承Object对象,因此不论什么样的Java对象,其大小都大于8byte。
有了Object对象的大小,我们就可以计算其他对象的大小了。
Class NewObject {
int count;
boolean flag;
Object ob;
}
其大小为:空对象大小(8byte)+int大小(4byte)+Boolean大小(1byte)+空Object引用的大小(4byte)=17byte。但是因为Java在对对象内存分配时都是以8的整数倍来分,因此大于17byte的最接近8的整数倍的是24,因此此对象的大小为24byte。
这里需要注意一下基本类型的包装类型的大小。因为这种包装类型已经成为对象了,因此需要把他们作为对象来看待。包装类型的大小至少是12byte(声明一个空Object至少需要的空间),而且12byte没有包含任何有效信息,同时,因为Java对象大小是8的整数倍,因此一个基本类型包装类的大小至少是16byte。这个内存占用是很恐怖的,它是使用基本类型的N倍(N>2),有些类型的内存占用更是夸张(随便想下就知道了)。因此,可能的话应尽量少使用包装类。在JDK5.0以后,因为加入了自动类型装换,因此,Java虚拟机会在存储方面进行相应的优化。
引用类型
对象引用类型分为强引用、软引用、弱引用和虚引用。
强引用:就是我们一般声明对象是时虚拟机生成的引用,强引用环境下,垃圾回收时需要严格判断当前对象是否被强引用,如果被强引用,则不会被垃圾回收
软引用:软引用一般被做为缓存来使用。与强引用的区别是,软引用在垃圾回收时,虚拟机会根据当前系统的剩余内存来决定是否对软引用进行回收。如果剩余内存比较紧张,则虚拟机会回收软引用所引用的空间;如果剩余内存相对富裕,则不会进行回收。换句话说,虚拟机在发生OutOfMemory时,肯定是没有软引用存在的。
弱引用:弱引用与软引用类似,都是作为缓存来使用。但与软引用不同,弱引用在进行垃圾回收时,是一定会被回收掉的,因此其生命周期只存在于一个垃圾回收周期内。
强引用不用说,我们系统一般在使用时都是用的强引用。而“软引用”和“弱引用”比较少见。他们一般被作为缓存使用,而且一般是在内存大小比较受限的情况下做为缓存。因为如果内存足够大的话,可以直接使用强引用作为缓存即可,同时可控性更高。因而,他们常见的是被使用在桌面应用系统的缓存。
参考:
http://pengjiaheng.iteye.com/blog/518623
http://www.cnblogs.com/shenliang123/archive/2011/10/27/2226903.html
http://pengjiaheng.iteye.com/blog/519471