`

关于Java占用内存的研究 (转载请注明作者zms)

    博客分类:
  • Java
 
阅读更多

版权声明 :转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://canyousee.blogbus.com/logs/3795658.html

最近对程序占用内存方面做了一些优化,取得了不错的效果,总结了一些经验
简要说一下,相信会对大家写出优质的程序有所帮助
下面的论述针对32位系统,对64位系统不适用,后叙

经常你写了一个程序,一测试,功能没问题,一看内存占用也不多,就不去考虑其它的东西
了。但可能程序使用了一个什么数据结构,会当数据规模变大时,内存占用激增。

基本&关键的问题是,Java里各种东东占多少内存?????????

对于primitive类型,有8个
byte short int long float double char boolean 它们的长度分别是
1  2  4  8  4  8  2 1
这个不罗嗦了,举例来说
long[] data=new long[1000];
占用内存  8*1000 bytes
此外,data本身是一个Object,也占用内存若干,后叙,当然它针对  8*1000来说,忽略不

再说Object的占用,在说这个之前,先说说引用,一惯的说法是
Java里没有指针了,只有引用,引用是安全的

这个说法没错,但是从机理上来说,引用就是指针,只是jvm对指针的使用检查和限制很多
,这个引用/指针变得很安全

直接来结论:一个引用占4byte ,在32位系统上

Object obj=null;        //4byte
Object[] objs=new Object[1000]; //至少4*1000byte

你看我定义了一个 obj,还是null,就占4byte
定义了一个 objs,1000个元素,但都是null啊,就都每个占4byte
是的!!!!!
虽然obj==null,但它已经是 一个引用,或者说一个指针了
指针也要占地方啊!!!!啊!!!!啊!!!!

接下来,直接给另一个结论: Object占8byte,注意,纯Object

Object obj=new Object();  //多少????

8byte?? 错!! 12byte,忘了还有一个引用,8byte是Object的内容
记住  Object obj=new Object(); 占12byte

Object[] objs=new Object[1000];
for(int i=0;i<1000;i++) {
  objs[i]=new Object();
}

至少占用  12*1000 bytes

推论: Object占12bytes,似乎和上面的结论矛盾??!!
没有!! 不管Object,没有被垃圾回收之前,总得被别人引用吧?
总的有指针指它吧?  既然指,那个引用or指针就要占地方啊 4byte
加起来是12byte,反正一个Object至少 12bytes

还是直接给结论,推导的过程我就都包办了,咱不是脏活累活抢着干么!!
一个Integer占 16 bytes

这时您可能会有疑问,Integer=Object+int,就是:
public class Integer {
  public int value;
}
Integer应该占 8+4=12 bytes啊
你说的有道理,但是jvm对所有的Object有限制!!
这个限制被我发现了,就是不管什么Object占的空间,要是8的倍数
12不是8的倍数,只能是16了!!!

推论:Byte也占16bytes!!!!!!!!!!!

问:
Byte[] bytes=new Byte[1000];
占用空间多少?
答:  约为(至少为) (16+4)*1000 bytes
好家伙!!!!!!!!


论题:数组空间占用怎么算?
我这里直接给结论了,推导这个花了更长的时间:
对于数组来说,数组这个Object有一个length属性,数组的元素相当于其成员
public class Array {
  public int length;
  //... 其它成员
}
对于数组,我们不是直接可以取length属性么,源于此

public byte[] bytes=new byte[1000];
System.out.println(bytes.length);  // 看,有length属性
上面的bytes换算过来是:
public class Array {
 public int length;
 public byte byte0;
 public byte byte1;
 ...
 public byte byte999;
}
上面的bytes占用的内存是:
4+[8+4 + 1*1000] = 4+ [1012]=4+1016=1020
4是 bytes这个引用,8是Object基占的,4是length属性占的
1000是1000个成员占的,本来是 1012,但要求是8的倍数,变成 1016了
总共是 1020
再如:
byte[] bytes=new byte[4];
的内存占用是:
4+[8+4+4*1]=4+[16]=20;

byte[] bytes=new byte[3];  也是 20

对于元素是Object的数组,Object也是当作其成员,(注意只有引用这个数组的空间,这个
可以推到普通Class上)

Byte[] bytes=new Byte[1000];
这个 bytes的定义相当于:
public class Array {
  public int length;
  public Byte byte0;
  .....
  public Byte byte999;
}
占用空间是:
4+[8+4+4*1000]+16*1000= 4+ 4016 + 16000  = 你自己算吧

推论:千万不要用  Byte[]  有20倍的差距!!!!!!!


你可能一下子没明白过来,没关系多琢磨一下,对于普通的class来说
,内容占用就是基加成员的占用,Object成员只记引用
public class Abc {
   public int n;
   public byte b;
   public Object obj;
}
它的内容占用是: [8+4+1+4]=24
所以  Abc one=new Abc()的占用是 4+24=28
提醒:对于 Abc的成员 obj没有计,如果要计入的话,循环这个过程就可以了。(琢磨一下

举例:

public class Abc {
   public byte b;
   public Object obj=null;
}

public class Def {
   public int n;
   public byte b;
   public Abc obj=new Abc();
}
问:
Def one=new Def(); //占多少?
答:
4+[8+4+1+4]+[8+1+4]=4+24+16=44


public class Abc {
   public byte b;
   public Object obj=null;
}

public class Def {
   public int n;
   public byte b;
   public Abc[] objs=new Abc[100];
   {
      for(int i=0;i<10;i++) {
         objs[i]=new Abc();
      }
   }
}
问:
Def one=new Def(); //占多少?
答:
kao,一下我也算不出来,不过我写了程序,可以算出来,你给它一个Object,它就能递归
的算出总共占了多少内存,这个程序不复杂,你也可以写出来。我等机会合适了再放出。

单独说一下String,String的结构是:
public class String {
    private final char value[];
    private final int offset;
    private final int count;
    private int hash; // Default to 0
}
所以,不考虑那个char[]的占用,一个String最少占用 [8+4+4+4+4]=24bytes
加上引用,共28bytes
所以
String s="";
占用28bytes!!!!! 尽管它的长度为0
如果精确的算,加上引用一个String的占用是
4+24+[8+4+2*length]
String s=""; 的占用是  28+16=  44
String s="ab" 的占用是  28+16= 44
String s="abc" 的占用是 28+24 = 52

要说的是,String是常用的类,这么看,String耗内存很多,所以jvm有优化,同样的内容
尽量重用,所以除了28是必须的外,那个char[] 很可能一样
比方说
String[] s=new String[1000];
for(int i=0;i<1000;i++) {
   s[i]=new String("abcdefasdjflksadjflkasdfj");
}
的占用的数量级是  28*1000,那 1000个字符串本身基本上不占内存,只有一份!!!!!

反正String 至少是 28,最多也可能是28!!!!!!!!


比较占内存的数据结构,这个很重要:
基本上就是  primitive的包装

实例:
我以前用一个
 Hashtable<String,Integer>的结构,有100万个元素
改为String[]+int[]后,内存占用改观不少,速度也很快
100万的String[] 快排一下,也就2秒多,查找用2分,和hash也差不多少

完!


说明:
1。 以上结论适用于32位系统,对于64位系统,有很多不同。反正结论是虽然64位系统能用
的内容更多了,但相同的程序占用内存也多了不少
2。 上面讨论的是类的实例占用的内存,没有考虑静态变量的占用。 静态变量引用的是算
在Class数据里的,内容的占用和实例无关,单独计算就可以了
3。 以上没有考虑 Class本身占的内存。 Class本身也需要占地方啊,就是类的结构,以及
静态变量的引用的占用。但是这个占用是静态的,不随实例变多而变多的。也不好统计出来
,想统计的话,看jvm源码里jclass的表示
4。 别人的劳动成果请尊敬,转载请注明作者zms

分享到:
评论

相关推荐

    基于Java语言的ZTO消息服务(ZMS)集群管理平台设计源码

    本项目为基于Java语言的ZTO消息服务(ZMS)集群管理平台设计源码,共包含899个文件,涵盖491个Java源文件、154个JavaScript文件、85个Vue组件文件、41个XML配置文件、30个PNG图片文件、25个CSS样式文件、19个SCSS...

    ZiiLABS推出全球首款1080p蓝光品质掌上型应用媒体处理器ZMS-08.pdf

    ZiiLABS推出的ZMS-08是一款革命性的1080p蓝光品质掌上型应用媒体处理器,它代表了移动媒体处理技术的重大突破。这款处理器是全球首款能提供如此高清画质的微型设备,特别适用于网络本、上网本、互联网电视、视频会议...

    ZMS-08:应用媒体处理器.pdf

    【ZMS-08 应用媒体处理器】 ZMS-08是由ZiiLABS公司推出的第三代富媒体应用处理器,它采用了H.264解码技术,为低功耗设备提供1080p蓝光品质的视频体验。这款处理器结合了ZiiLABS的干细胞计算阵列和1GHz的ARM Cortex...

    ZiiLABS公司ZMS-08媒体处理器为低功耗设备提供1080p蓝光品质.pdf

    本文主要介绍的是ZiiLABS公司的ZMS-08媒体处理器,这是一款针对低功耗设备设计的处理器,能够提供1080p蓝光级别的视频处理能力。ZMS-08处理器集成了多种功能,旨在提升下一代网络设备的富媒体处理性能,包括全高清...

    ZiiLABS推出全球首款1080p蓝光品质掌上型应用媒体处理器ZMS-08 (1).pdf

    ZiiLABS推出的ZMS-08媒体处理器,作为全球首款能够实现1080p蓝光品质的掌上型应用媒体处理器,毫无疑问地将移动设备的多媒体处理能力推向了一个新的高峰。 ZMS-08的发布,不仅仅是技术上的突破,更是对于未来移动...

    vedyna.zms-开源

    【vedyna.zms-开源】是一款基于开源软件理念开发的MIDlet应用程序,主要用于压缩SMS(Short Message Service,短信)文本内容。这款应用的核心功能是解决短信内容受限于传统160个字符长度的问题,使得用户能够发送...

    ZiiLABS推出全球首款1080p蓝光品质掌上型应用媒体处理器ZMS-08 (2).pdf

    这篇文章主要介绍了两个重要的技术产品,分别是ZiiLABS的ZMS-08媒体处理器和Avago的MGA-231T6低噪声放大器。 首先,ZiiLABS推出的ZMS-08是一款革命性的应用媒体处理器,它是全球首款能够提供1080p蓝光品质视频处理...

    ZMS-15T型湿式煤电钻维护保养规程.docx

    《ZMS-15T型湿式煤电钻维护保养规程》正是这样一套指导文件,它详细规定了设备的使用、维护、保养和检查的每个环节,旨在保障操作人员的安全,提高工作效率,延长设备寿命。 首先,对于操作人员来说,熟悉ZMS-15T型...

    灭火机器人设计zms.pdf

    灭火机器人是一种高科技设备,设计用于在危险环境中执行灭火任务,以减少人员伤亡。该机器人的设计基于单片机控制,结合电源电路、电机驱动、避障前进系统、火焰检测电路和灭火系统等组件。其中,单片机是整个系统的...

    zMS Open Source-开源

    【zMS开源游戏详解】 zMS Open Source 是一个独特且创新的开源项目,旨在为玩家带来全新的游戏体验。这款游戏融合了角色扮演游戏(RPG)与第一人称射击(FPS)元素,让玩家在游戏世界中自由切换游戏类型,极大地...

    ZMS5:在Python 3.7、3.8上运行

    标题 "ZMS5:在Python 3.7、3.8上运行" 暗示我们正在讨论一个名为ZMS5的系统或框架,它已针对Python 3.7和3.8版本进行了优化和测试。这个系统可能是一个内容管理系统(CMS),用于科学、医学、技术、管理和出版等...

    ZliLABS推出首款1080p蓝光品质掌上型应用媒体处理器ZMS-08.pdf

    1. **ZMS-08处理器**:ZliLABS推出的ZMS-08是一款1080p蓝光品质的掌上型应用媒体处理器,它专为低功耗设备设计,能够提供高清视频解码能力,采用H.264解码技术,确保了高质量的媒体体验。这款处理器的出现,标志着...

    网络技术-网络基础-正电子发射断层(PET)基础与临床研究.pdf

    **正电子核素标记的研究**:尽管已经有一些关于正电子核素标记的中药成分的研究,但将其应用于AD相关的中药成分如ZMS的报道较少。本研究的目标是探讨正电子核素标记中药有效成分的可能性,以及标记后的ZMS在体内的...

    微捷码帮助ziiLABS实现双倍性能和减半功耗的100核心ZMS-40处理器.pdf

    ZiiLABS的100核ZMS-40处理器就是这种合作关系的产物,它融合了96个StemCell媒体处理核心和4个1.5GHz ARM Cortex-A9 CPU,旨在提供卓越的多媒体处理能力和多任务处理性能。 ZMS-40处理器的设计目标是为Android手持...

    ZMS3:在Python 2.7上运行(稳定,可用于生产环境)

    以下是关于ZMS3系统的详细知识点: 1. **Python 2.7 支持**: - ZMS3选择了Python 2.7作为其基础开发语言。尽管Python 3已成为主流,但考虑到一些组织可能仍在使用Python 2,ZMS3的兼容性确保了这些用户也能顺利...

    zms:ZMS是ZTO Message Service的缩写,使用方与最大化解压缩,屏蔽各消息发生差异,可以将消息进行进行安装,管理,监控,重置管理的平台

    ZMS 什么是ZMS? ZMS是ZTO Message Service的缩写,使用方与累解分解,屏蔽各消息发生差异,可以将消息进行进行安装,管理,监控,重置管理的平台。 ZMS能做什么? 客户端快速收发 屏蔽消息接收方使用不同类型互换...

    java

    In this completely up-to-date volume, Herb Schildt, the world's leading programming author, shows you everything you need to know to develop, compile, debug, and run Java applications and applets....

    ZMSForms:ZMS(基于 Zope 的 CMS)的配方师表格

    ZMS表格 ZMS(基于 Zope 的 CMS)的简易配方表格 2015 年 Niels Dettenbach / Syndicat IT & Internet GPLv2 许可 ZMSForms(又名 KForms)允许最终用户兼容处理 HTML 表单、联系表单,包括 ZMS 网站中的表单逻辑。 ...

Global site tag (gtag.js) - Google Analytics