近段时间,项目要求对java的内存有要求,客户希望不要老是要他们扩大内存,所以此过程中了解了一些问题。
越想觉得,java越不是。1,基础对象占有内存 byte,char,short,int,long,float,double分别为 1,2,2,4,8,4,8,byte;
   包括后Byte,Short,Integer,Long....等分别为 16,16,16,16,都是byte
   本来是 1字节的 byte包装后占 16字节!! 太不象话了,白用我的内存。除了一个Object 8byte指针其它浪费。
2, Object 8byte指针,就算定义个空对象,也一样占8byte 我觉得一个指针要 8个字节吗?有必要吗?我的内存啊。
   2^64= 18446744073709551616 byte =17179869184G 有可能用这么大的内存地址吗?(欢迎内行发言)。
   个人觉得:6个byte足也,281474976710656 = 262144G 不知道有什么难处要用 8byte.
3, Byte 用了 16字字节,真是想不通:8(指针)+8;浪费7byte
4, Short用了 16字字节,真是想不通:8(指针)+8;浪费6byte
5, Integer 用了 16字字节,真是想不通:8(指针)+8;浪费4byte
6, Long    用了 16字字节,:8(指针)+8;没浪费。
7, Float   用了 16字字节,真是想不通:8(指针)+8;浪费4byte。
8, Double  用了 16字字节,:8(指针)+8;没浪费。
9, BigDecimal  用了 32字字节,:8(指针)+24;除指针外 16不够? 太猛了吧?吃内存啊!!!
10,object = new String();  用了 40 字字节,:8(指针)+32;好象内存没花钱一样。
11 int[] a =new int[]{0};  也是16字节
11 long[] a =new long[]{0};  也是24字节这么基础的东西,做得这样烂,java倒底怎么了? 难道为吃内存而生? 现在知道,为什么java在游戏上插不上足,这样根本是不行的。不用对象,又难以区分数据库为空的数据,真是进退两难。
为什么java不在新版本上来个新架构啊,这样下去只有一条:死.........

解决方案 »

  1.   

    汗啊,真不知道你是怎么算出来的
    算这个有意义吗?你认为你算的准确吗?
    你以为java就只吃了你列出的那些内存吗?
    得了,你不如去搞C吧,内存你自己控制,想怎么搞怎么搞
    哈哈~
      

  2.   

    开始好喜欢的,.net也是,java也是,后来慢慢发现,问题太多了。这只是一部分。
    喜欢java总希望会改正 从1.3,1,4,1.5,1.6都是这样,我急了。为什么不能再好些。
      

  3.   

    我测试的1.4,1.5
    我拿国外的一个程序测试的(1.5java内部已经可以测试了:java.lang.instrument.Instrumentation.getObjectSize(o)).
    测试用的外国程序:
    import java.util.ArrayList;
    import java.math.BigDecimal;/**
     * @author guishuanglin 2008-12-2 原程序作者:Vladimir Roubtsov
     * 
     */
    public class Sizeof {
    public static void main(String[] args) throws Exception {
    // Warm up all classes/methods we will use
    runGC();
    usedMemory();
    // Array to keep strong references to allocated objects
    final int count = 100000;
    Object[] objects = new Object[count]; long heap1 = 0;
    // Allocate count+1 objects, discard the first one
    for (int i = -1; i < count; ++i) {
    Object object = null; // Instantiate your data here and assign it to object // object = new Object();
    // object = new Integer (i);
    // object = new Long (i);
    // object = new String ();
    // object = new byte [128][1];
    // object = new Float(1);
    // object = new Double(1);
    // object = new BigDecimal(1);
    object = new String(); if (i >= 0)
    objects[i] = object;
    else {
    object = null; // Discard the warm up object
    runGC();
    heap1 = usedMemory(); // Take a before heap snapshot
    }
    }
    runGC();
    long heap2 = usedMemory(); // Take an after heap snapshot: final int size = Math.round(((float) (heap2 - heap1)) / count);
    System.out.println("'before' heap: " + heap1 + ", 'after' heap: "
    + heap2);
    System.out.println("heap delta: " + (heap2 - heap1) + ", {"
    + objects[0].getClass() + "} size = " + size + " bytes");
    for (int i = 0; i < count; ++i)
    objects[i] = null;
    objects = null;
    } private static void runGC() throws Exception {
    // It helps to call Runtime.gc()
    // using several method calls:
    for (int r = 0; r < 4; ++r)
    _runGC();
    } private static void _runGC() throws Exception {
    long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE;
    for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {
    s_runtime.runFinalization();
    s_runtime.gc();
    Thread.currentThread().yield(); usedMem2 = usedMem1;
    usedMem1 = usedMemory();
    }
    } private static long usedMemory() {
    return s_runtime.totalMemory() - s_runtime.freeMemory();
    } private static final Runtime s_runtime = Runtime.getRuntime();
    } // End of class
      

  4.   

    现在很多系统为了加快速度,都做了缓存的,小系统当然不存在这个问题,算算吧。
    本来用 byte 只需要 100M,如果用 Byte就要 1.6G
    (你有多少米?内存地址能搞多大?32? 64?)
    本来用 int  只需要 400M,如果用 Integer就要 1.6G如果大系统连操作系统都支持不了多大的内存,现在我们的系统日产数据: 300多万条(20多列),内存数据放得太多,服务器受不了。客户已经把内存加到 4G了。
      

  5.   

    不用对象也行啊。
    只要你愿意把1 个方法 public void h(Number arg),换成 8个方法来写。
    public void h(byte arg)
    public void h(short arg)
    ……
    当涉及到范型的时候,本来一个类就实现的设计,换成8个类来写。
      

  6.   

    到了必要时,会自动调用 GC的,现在我们的系统日产数据: 300多万条(20多列),内存数据放得太多,服务器受不了。客户已经把内存加到 4G了。 
    ....你产生了那么多数据,难道全部保存到内存中,也太强了吧
      

  7.   

    不要总是用过程思维,OO都广告了多少年了这些包装过后的东西:Byte,Short,Integer,Long
    是对象,对象就有属性和方法,怎么会是指针+数据长度.........再说了
    你拿一个对象去和基本类型比内存占用,有意义吗?面向对象编程的目的是什么??
      

  8.   

    楼上你跑题了,你觉得Byte使用 16个字节,正常吗?与Integer一样,这样用Byte还有什么意义?
      

  9.   


    就是啊  sun公司那么多高手都没觉得有必要该  楼主咋这么激动啊?
      

  10.   

    qusic,dice_com是不是理解问题?
    谈的与你的相法不一个问题。看清题。
      

  11.   

    楼上应当年看看另一个贴子,高手的回答。
    http://topic.csdn.net/u/20081202/15/20ba8be0-04c7-4e54-bdd9-d2f6b3c1f413.html?seed=53448279
      

  12.   

    任何工具都有其适用范围,就LZ的使用场景,我觉得根本就合适用JAVA。
      

  13.   

    本来用 byte 只需要 100M,如果用 Byte就要 1.6G 我靠 ,做的什么比较,你杀死一只蚂蚁和你杀一个人去比较,你有多少命够毙.
      

  14.   

    为什么不在数据库那边设置默认值.  你有了默认值. 还在乎null的情况么?                          解决问题.又不是只有一种方法. 如果你这真的是一种问题的话. 那java社区早都炸锅了. 没你说的份根本.
      

  15.   

    声明:
    1,我不是说java比别人差,也没有针对java的开发者,请大家就这个问题发表意见,java这样做是否可取.2, 上面的数据我不敢有半点差错,都是经过详细测试取得的,并且在jdk1.6 也提供了方法可以测试,大家可试试。3, 做为java的开发者,我从2001年开始做开发,并不是什么新手,PB,delphi,vb,GX,Magic,java(20042002年开始),.net(2002年开始),在java方面,一直追求高性能的框架设计。
       同时在j2ee,ejb,ejb3.0,hibernate,ibatis,jni,spring,web service方面,还算是个老手。并且经常学习新的东西(这也是我一直从2001年开始一直在csdn里的原因)。
       所以没不会平白无故的说java不好,我只是觉得java在这方面应当可以做得更好,因为目前的框架还是沿用老式的体系与设计,而.net却不断进步,我是急啊。
    4, 请大家只说价问题,不需要对人,再者,大家如果需要更深入JVM也需要这方面知识,
      做为一个java开发者我认为:要指出并知道,自己喜欢的东西有什么问题,这样才能更好的开发出好系统。
                                喜欢它宠爱它,但不要过份的宠坏它。
      

  16.   

    这可能和jvm有关,java的发明者不可能没想到这些,包装可能是为了跨平台,不至于出现不同平台的长度不一样。
      

  17.   

    java程序是可以成编译成平台特定的,不过我没试过,那样应该会解决你说的内存占用问题,不过,加几条内存是个最简单的解决问题,现在2G才140.
      

  18.   

    java在这方面的问题,日益显得严重,否则,在1.5,1。6等版本中,用cache来解决速度与内存问题。
    所以java是知道这个问题,问题是改动太大,影响到根本的体系了。
    大家可以在1.5测试:
    Long a = 2L; 
    Long b = 2L; 
    System.out.println(a == b);
    //结果为ture
    两个对象的引用是一样的。
    但是你测试:
    Long c = 1000L; 
    Long d = 1000L; 
    看看?相引用一样吗?但是这种改变远远不能解决根本问题。只能是1.5速度快点点。
      

  19.   

    byte 1字节,而Byte用掉 16byte内存,这样做实在太草率了。
    浪费太多。
      

  20.   

    Java毕竟还是使用率第一的语言,虽然我还在努力试着喜欢上它。
      

  21.   


    /**
     * 
     */
    package test;/**
     * @author - yy
     * @time   - Dec 3, 2008 10:58:15 AM
     */
    public final class TestObject {  // 测试对象
    //  private boolean b1;    如果类里面不到8个(含8个)boolean  ,TestObject 占内存是16 bytes;
    //  private boolean b2;    9-16个boolean,TestObject  占内存是24 bytes; 以此类推
    //  private boolean b3;
    //  private boolean b4;
    //  private boolean b5;
    //  private boolean b6;
    //  private boolean b7;
    //  private boolean b8;
    //  private boolean b9;
    //  int i1;                如果类里面不到2个(含2个)int  ,TestObject 占内存是16 bytes;
    //  int i2;                2-4个int,TestObject  占内存是24 bytes; 以此类推
    //  int i3;  
    //  long L1;               多一个long就增加8bytes
    //  long L2;// String的字段有
    //    char value[]=new char[0]; // 8bytes
    //    int offset;  \
    //    int count;    |  8bytes
    //    int hash;    /
    //    long serialVersionUID = -6849794470754667710L;  // 8bytes
    //    ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];// 8bytes
    //    加上自身的8bytes
    // 正好40bytes//  其他类型的类似
    //  应该可以解释了吧
    }
      

  22.   

    包装类不是为了节省系统开销而存在的.
    同样:面向对象也不是为了节省系统开销而存在的.同时,内存的占用与释放不但来自于底层结构,真正重要的还是项目设计.
    如同你要导入2000万条记录一样,在一个事物里控制,就是用汇编来写代码,内存也是不够的.另外,包装类的内存占用计算貌似是错误的,它比你想象中更大,严格遵守了Java类的标准,有自己的属性和行为.
    而BigDecimal类有可能是最大的(这个没计算).
      

  23.   

    JAVA从它诞生开始,就以吃内存和速度慢而闻名,楼主说的 Byte 占用多少字节这档子事,估计从 java 还在吃奶时就已经存在了,但是这么多年来也都活下来了,并且活得越来越精神,不但企业用它,而且小设备也一直用它。随着这些年来硬件成本越来越低,内存价格更是一路往下跌,所以针对楼主的投诉,JAVA的设计者可能跟本不会考虑。
      

  24.   

    cangyue87:没算过怎么说我的是错的? 你还是算算再来说。
      

  25.   

    xiaozhimin1978:说的实在,java可能根本不会理会。
      

  26.   

    yywl62:我有比你更详细的测试,要不然,我算不出来上面的结果。
      

  27.   

    我只是根据结果再解释原因的
    比如说为什么String占用了40 bytes;ps: 另外上面的String的我也解释错了// String的字段有
    //    char value[]=new char[0]; // 16bytes
    //    int offset;  \ 2个共用 8bytes
    //    int count;   /
    //    int hash;    // 8bytes
    //    long serialVersionUID = -6849794470754667710L;  // 类属性不算,因为共用一个
    //    ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; // 类属性不算,因为共用一个
    //  加上自身的8bytes
    // 正好40bytes
      

  28.   

    Byte一个Byte类型的引用在栈中占用的内存为4字节.一个Byte类型的实例在堆中占用不一定:
    value属性,如果该byte值小于在-127-128之间,直接共享byte常量池中的值.否则占用4字节
    byteValue()方法,不知道它有多大...两条机器码长度,8个字节以内?....天知道...
    shortValue()方法,不知道它有多大...
    intValue()方法,不知道它有多大...
    longValue()方法,不知道它有多大...
    floatValue()方法,不知道它有多大...
    doubleValue()方法,不知道它有多大...
    toString()方法,不知道它有多大...
    hashCode()方法,不知道它有多大...
    equals(xxx)方法,不知道它有多大...
    compareTo(xxx)方法,不知道它有多大...构造方法和静态方法伴随JVM同步加载,所有Byte实例共享,应该不计算在内喵~~`
      

  29.   

    楼上,很多大网站都选择用PHP,就是因他快,包括IBM在内的大公司,都是支持PHP的。
      

  30.   

    cangyue87 :如果对我测试的程序不放心,你直接用JDK1.6测试,1.6已经自己有方法计算内存空间了。
      

  31.   

    getRuntime方法只能统计当前的运行时对象,
    它统计的是当前栈的总消耗.gc的调用同样是不可控制的,
    不过看楼主的运行效果貌似回收很及时的样子,
    也许是因为程序短小的缘故喵???
      

  32.   

    那是开发快,具体效率得看代码,无论php还是java,网站的运行效率都和语言无关的.
      

  33.   

    一、基础数据封装类的16个字节,这个就是“面对对象”的代价。如果面对过程,在这里设计的会变得繁复,而且复用性差。这个问题如果想不明白的话。你可以去比较一下在C++里面的string使用和在java中的string使用就可以体会到了。
    二、关于数组大小的问题,本身是可以增加大小的。
    1.采用固定大小的办法是为了提高性能,这个应该都明白。那么关于这个大小是多少的问题,太小了,频繁增加性能反而降低,太大了又不能起到提高性能的作用。这个平衡点,我觉得sun找得还可以。
    2.如果只在需要的时候给内存,则需要另给内存保留指针,该指针指向新增元素地址。频繁增加,不但更占用内存,而且降低性能。引伸出的问题是实际是不是需要频繁增加的呢,我觉得是的,尤其是一些高级类里面,不断地要掉父类构造和释放方法时。
    总结、短时间内不会改变,即使改变也是增大。减小几乎不可能。
      

  34.   


    象Integer,Long包装类,是只保存被包装的数据。方法是另一回事。
      

  35.   

    如果还不清楚:"Integer,Long包装类,保存了什么数据,N多方法怎么保存的问题"。
    如果这样的基础还不知道,建议同志们看<<龙书>>后再反对我的问题。回:likgui
    java 设计有问题,这与回到机器时代没有相关联,是两回事吧,这里并没有说与其它语言的差别.
    说的是java本身出现的设计问题。
      

  36.   

    同意http://topic.csdn.net/u/20081202/15/20ba8be0-04c7-4e54-bdd9-d2f6b3c1f413.html?seed=53448279 说的!!!
    另外不认为Java有多牛,每个语言都有自己优势的地方,在某些方面Java也是废材!
      

  37.   

    LZ你的思维还停留在面向过程上面JAVA是纯OO的语言。为了实现OO的特性,吃内存是没办法的事情,但是在运行效率上的牺牲换了的是开发速度和可维护性上的巨大进步。再说JAVA的定位本来就没有过多的考虑对游戏这类极其重视运行效率的程序的支持。应该说寸有所长,尺有所短,针对的目标不一样,使用的体系就不一样,在JAVA不擅长的这方面去死抠没多大意义
      

  38.   

    硬件便宜了,那是客观现象。
    但是假如硬件是越来越贵了,那java该怎么办?
      

  39.   

    好久没有这么热闹了
    楼主的心情也是可以理解的,大家无非都是在担心java的发展嘛
    希望大家讨论不要带情绪。大家都是在java这条路上发展的,是属于同一个方向,都是同一条船上的,不要为这些事争得面红耳赤。我想发表一下自己的看法:
    1.楼主的那个项目看起来规模蛮大,但是不管怎么说,楼主项目的设计是有问题的;
    而且,一个服务器4g的内存,也不奇怪。客户埋怨产品不好,从古至今,一直都是存在的,
    我还想用1M的内存去跑网游呢,呵呵,难道客户那边的反馈就一定是客观的吗?
    2.楼主的担心也不无道理。不过,我想我们作为开发者,还是应该首先从自己的代码入手。至于jvm,jdk,还是让sun那帮人忙活吧,除非你能搞出自己的更有效的产品出来。
      

  40.   


    那你就不能用C++做啊?看你这么强, 用C也行啊。 如果现有项目是java, 可以使用JNI吧?
      

  41.   

    berlou: JIN 在我们项目中是有的。而且不少。
      

  42.   

    感觉你们的项目不应该用java开发,用C++或者C都是比较好的.
    既然都用那么多的JNI了,干脆就不再用Java了.
      

  43.   

    java做的这些都是为了平台通用性而设计的
      

  44.   

    我觉得,"为了平台通用性而设计" 找不到理由支撑。
    而且我想在这次技术大会,有人会提出java其它核心错误设计,不信大家可以等待。
    当然不一定是我说的问题,可能是java更严重的设计问题。
      

  45.   

    貌似C也差不多吧!!
    int,char占用差不多。。你要修改基础类,支持你,等待你的喜讯。内存地址总线查的时候就以一个Byte为准。
      

  46.   

    Sun公司的首席工程师——Mark Reinhold一直主张将Sun JDK模块化。他举例说明了复杂性如何损害这个平台,以及JDK 6 update 10版的Java Kernel和Quickstarter的功能只是解决了JDK长期关联成长导致的表面诟病请看更大的,更严重的问题:http://java.csdn.net/page/b4e7cf8c-3854-45ba-941f-3e8ef4866624
      

  47.   

    具体底层怎么回事我不知道,暂时还没出现内存不够用的情况。
    lz说的那些基础数据什么的看着确实占内存不少,但一个设计好的方法里面要用到多少呢?即使是for循环,内部的变量在一个循环结束后就会把内存释放了吧?循环外部你能定义多少变量、对象呢?如果你一个方法体写了1M+,定义了N*N的变量、对象,那我无语了,,,多少内存也不够用的啊,,,
      

  48.   

    任何事物都不可能完美。
    你有经历过用c写webservie的经历吗?那时你会体会到用java是多么美好。
      

  49.   


    在一个系统很大时需要缓存数据,比如:用户,系统配置,字典值等等,单用户现在已经达到1.35亿。用缓存来增加响应能力。
    减少对数据库的冲击。这些变化很少的数据,没必要不断查询数据库。
    再者使用一些工具,象hib之类也会有部分缓存。
      

  50.   

    首先要理解java的追求目标是安全,而不是高效率.
    java在处理一写基本类型是,都是采用的unicode编码,目的是让只要运行在jvm上的程序都是世界统一的,不论任何平台,在上层语言上都是统一的.然后sun在机器语言这一层次上编写出各种平台的jvm.
    其实sun公司是非常有远见的,大家想想,所着用java的人越来越多,我们在硬件上会不会跟着软件来设计.而不用在让jvm运行在其他平台之上.
    微软为什么要推出.net平台?就是为了与java强市场吗.但是个人觉得.net做的仅仅是让一些语言写出的程序在汇编这一层统一起来,我觉得从策略上远比不上sun公司
      

  51.   

    100楼是我的喵~~``当我看到楼主说龙书的时候就只能感叹偶的神呐~``
    记得Sun有明确说明包装类和普通类在JVM上保持一致,实例方法在JVM的堆里需要单独划分,如果我理解错了,还麻烦求一个出处喵~``不过这个跑题了吧,楼主提出的问题不归属底层设计喵~`
    面向对象(包装类)的开销必然比面向过程(基础类型)更大,它以更大的消耗为编码的逻辑服务.
    就像现在的面向事物或者面向插件的开发,执行效率必然有更大的消耗----因为它出来的初衷节省的就不是内存.如果公司里同时有Java和C++两个部门.
    也许就会经常听C++朋友们抱怨:我们C++的被分去一个糟糕的项目,那实在太坏了-----C++起比Java,要做烂尾可是真彻底,真容易.毕竟,我们有不同的关注重点,和不同的烦恼喵~!