`
和你在一起
  • 浏览: 678106 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM调优总结(二)-一些概念

阅读更多

 

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时,肯定是没有软引用存在的。

 

弱引用:弱引用与软引用类似,都是作为缓存来使用。但与软引用不同,弱引用在进行垃圾回收时,是一定会被回收掉的,因此其生命周期只存在于一个垃圾回收周期内。

 

    强引用不用说,我们系统一般在使用时都是用的强引用。而“软引用”和“弱引用”比较少见。他们一般被作为缓存使用,而且一般是在内存大小比较受限的情况下做为缓存。因为如果内存足够大的话,可以直接使用强引用作为缓存即可,同时可控性更高。因而,他们常见的是被使用在桌面应用系统的缓存。

39
2
分享到:
评论
13 楼 和你在一起 2011-07-05  
想想看jvm实现不会这么烂的,1bit就能搞定的事情,他怎么会使用32bit去存呢?即便是你去实现估计你也会考虑优化的,所以int想想也不会。

一个简单的实验:

public static void main(String[] args) {
     byte[] a = new byte[16000000];
}

java启动参数设置一个很小的堆,如-Xmx16m,如果你new的空间大于这个,则会OutOfMemery。
修改你new的类型会发现,byte的数量=boolean的数量>char>int。结果自然明了。


546144153 写道
hongjn 写道
mathfox 写道
Boolean大小(1byte)

这个说的是不是不对啊

我记得看jvm的时候,jvm specifaction明确说了,boolean是用int再储存的。

是1byte没错 呵呵

不一定吧  boolean确实会被存成int  你确定是1byte?

12 楼 546144153 2011-07-01  
hongjn 写道
mathfox 写道
Boolean大小(1byte)

这个说的是不是不对啊

我记得看jvm的时候,jvm specifaction明确说了,boolean是用int再储存的。

是1byte没错 呵呵

不一定吧  boolean确实会被存成int  你确定是1byte?
11 楼 hongjn 2009-12-26  
mathfox 写道
Boolean大小(1byte)

这个说的是不是不对啊

我记得看jvm的时候,jvm specifaction明确说了,boolean是用int再储存的。

是1byte没错 呵呵
10 楼 mathfox 2009-12-07  
Boolean大小(1byte)

这个说的是不是不对啊

我记得看jvm的时候,jvm specifaction明确说了,boolean是用int再储存的。
9 楼 和你在一起 2009-12-05  
@xinglongbing
谢谢你的建议!我会尽力完善:)不过,也希望你能多多谅解,其实这些文章里面随便一个主题展开或许都有说不完的东西,我也很难做到面面俱到。

1. 我确实没有在64位机器上跑过,上面的数据是在32位机器上测试的结果。

2. 当初之所以把这些很基础的东西翻出来说一遍,主要是希望大家能看到问题的本质,不要被很多技术迷了眼,其实真正能解决问题的或许就是当年学校里学的那些基础。有些时候回过头去看看,会有“暮然回首,那人却在灯火阑珊处”的感觉。因此,那篇文章并不是针对SUN JVM来说的:)

对象要放在栈中确实可以,只不过是有前提的,如果这个对象需要动态变化,你觉得他还能放在栈中吗?如果这个对象是一个很大的对象,又能放在栈中吗?
C#我不是太熟,不过“结构体”如果和C一样的话,它本质就是基本类型的集合,它的大小一般情况下应该是固定的,这样的话,放栈中也没什么奇怪的。
另外一篇文章提到的,应该也类似。

其实要回答这些问题,只要能清晰的知道栈是什么就可以了。
8 楼 xinglongbing 2009-12-05  
  楼主总结了JVM的不少知识点,对我们初学者帮助挺大的。只是感觉有些地方不太严谨,只是谈及表面现象:比如一个空对象占8字节,只是简单的做计算没有谈及本质,楼主计算的应该是32位的SUN JVM下对象大小而不是64位JVM的吧?
  上一篇的堆和栈的总结,其实只是针对SUN JVM实现做的总结,并不能代表所有的实现:对象本身完全是可能放在栈中的,栈中只存放基本数据类型和引用类型仅仅是一种实现方式而不是定理。像C#中不就有结构体放栈中吗,而且很多研究JVM的有把对象放栈中的:http://galaxystar.iteye.com/blog/473355这篇文章讲解挺不错。
7 楼 和你在一起 2009-11-26  
@zzl_zhang
“虚引用”我理解也有限,特别是用在什么地方、什么时候用。所以上面就提了一下,不知道的东西还是别放在blog上,呵呵,可以从别处搬一段过来,不过搬过来我也不知道是啥:)

这个8btye是程序算出来的,算法简单,就是new很多对象,用当前消耗的内存数再除下new的对象数量。至于一个空对象为什么是8btye,里面存了哪些东西,这个就要看看其他的东西了。
6 楼 zhwayne 2009-11-26  
zzl_zhang 写道
虚引用
好像没在这章里介绍
一个空Object对象的大小是8byte
弱弱的问一下: lz 对内存大小判断的根据是什么?

应该是对象本身的地址+GC回收时可能需要的某些标记
5 楼 zzl_zhang 2009-11-26  
虚引用
好像没在这章里介绍
一个空Object对象的大小是8byte
弱弱的问一下: lz 对内存大小判断的根据是什么?
4 楼 flying_all 2009-11-23  
我们的项目总是出现OOM的问题。没查明白为什么。继续学习。
3 楼 ftp51423121 2009-11-19  
呵呵,谢谢了~
2 楼 和你在一起 2009-11-18  
@zhxing
实践出真知,碰到问题解决问题的过程本身也就是学习的过程:)jvm这块主要涉及到系统性能调优方面的事情,最简单的就是解决内存泄露相关的问题。
工作时间不长,不过从接触java算得有个5、6年了吧
1 楼 zhxing 2009-11-18  
lz是怎么学习的,也想了解下jvm 的学习方法。。
ps:lz 工作几年了有这个基础哦

相关推荐

Global site tag (gtag.js) - Google Analytics