精华内容
下载资源
问答
  • 是不是在想oracle公司为啥不提供计算java对象大小的方法呢? 在企业开发中,前后台传递数据,如果数据比较大,进行持久化传递将会造成对象无法被虚拟机回收,进而导致内存泄漏,但一般是由于对象不较大引起,因此...
    是不是经常通过jvisualvm.exe来观察堆对象占用内存的变化?是不是在想oracle公司为啥不提供计算java对象大小的方法呢?
    在企业开发中,前后台传递数据,如果数据比较大,进行持久化传递将会造成对象无法被虚拟机回收,进而导致内存泄漏,但一般是由于对象不较大引起的,因此需要对这些对象进行处理。google查询了一些资料,研究和整理如下:

    1、利用序列化方法,这个经测试时比较接近的;
    2、根据对象的大小进行估值;
    3、使用虚拟机提供的函数,动态的,有时准确,有时不准确;
    4、通过反射获取对象的大小,理论比较好,但没实现;
    5、通过代理的方法来得到

    下边主要说下序列化和虚拟机函数的方法。
    序列化时通常把一个对象序列化到一个字节buffer里,那么就可以获得这个buffer的字节数。今天,在工作中,突软想到这样做太浪费空间,看了Java的ObjectOutputStream这个类的源码,发现也可以如下做,只计数,不产生字节转移,那么就不会耗费内存空间了。

      public final class SizeCalculator {

      public static int calcSize(java.io.Serializable o) {

      int ret = 0;

      class DumbOutputStream extends OutputStream {

      int count = 0;

      public void write(int b) throws IOException {

      count++; // 只计数,不产生字节转移

      }

      }

      DumbOutputStream buf = new DumbOutputStream();

      ObjectOutputStream os = null;

      try {

      os = new ObjectOutputStream(buf);

      os.writeObject(o);

      ret = buf.count;

      } catch (IOException e) {

      // No need handle this exception

      e.printStackTrace();

      ret = -1;

      } finally {

      try {

      os.close();

      } catch (Exception e) {

      }

      }

      return ret;

      }

      public static void main(String[] args){

      System.err.println(calcSize(1));

      }

      }
    原文链接:http://www.linuxidc.com/Linux/2010-01/24222.htm

    2、通过获取new对象前和后 Runtime.getRuntime().totalMemory( )计算它们的差值,还是有参考价值的,至于有的说先让虚拟机回收,这个不可行,因为虚拟机执行回收是自动的,并不能直接调用虚拟机进行对象回收的。
    展开全文
  • 空闲列表:如果Java的内存不是规整的,则需要由虚拟机维护一个列表来记录那些内存是可用的,这样在分配的时候可以从列表中查询到足够大的内存分配给对象,并在分配后更新列表记录。 选择哪种分配方式是由 Java 堆...

    类加载完成后,接着会在Java堆中划分一块内存分配给对象。内存分配根据Java堆是否规整,有两种方式:

    • 指针碰撞:如果Java堆的内存是规整,即所有用过的内存放在一边,而空闲的的放在另一边。分配内存时将位于中间的指针指示器向空闲的内存移动一段与对象大小相等的距离,这样便完成分配内存工作。
    • 空闲列表:如果Java堆的内存不是规整的,则需要由虚拟机维护一个列表来记录那些内存是可用的,这样在分配的时候可以从列表中查询到足够大的内存分配给对象,并在分配后更新列表记录。

    选择哪种分配方式是由 Java 堆是否规整来决定的,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。

    在这里插入图片描述

    展开全文
  • 想明确了解一个对象,比如VO,BO,List占用多少内存空间,可使用此类获得,在评估一些大批量导出时很有用,能够准确评估出一次查询的返回结果list占用多少内存空间 package com; import java.lang.reflect.Field...

    想明确了解一个对象,比如VO,BO,List占用多少内存空间,可使用此类获得,在评估一些大批量导出时很有用,能够准确评估出一次查询的返回结果list占用多少内存空间

    package com;


    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    import java.util.*;
    //一个引用:4字节
    //一个Object:8字节
    //一个Integer:16字节 == (8 + 4+8-1) / 8 * 8
    //一个int:4字节
    //长度为0的数组大小:JRo64=24,  Sun32=12


    import com.pcm.order.edit.business.model.OrderHeaderBO;


    //引用大小,如Object = null:                    JRo64=JRo32=4, Sun32=4, Sun64=8
    //无成员的对象大小,如new Object();:     JRo32=JRo64=8, Sun32=8, Sun64=16
    //new byte[0]:                        JRo32=JRo64=8+8 Sun32=8+4, Sun64=16+8


    //长度l的byte数组:(l+12+8-1)/8*8
    //长度l的char/short数组:(l*2+12+8-1)/8*8 == (l+9)/4*8
    //长度l的String:(l+1)/4*8+40
    //长度l的int数组:(l*4+12+8-1)/8*8 ==(l+4)/2*8
    //长度l的long数组:(l*8+12+8-1)/8*8 == (l+2)*8


    public class Occupy {
     public static void main(String[] args){
     Occupy oc = new Occupy((byte) 4, (byte) 8, (byte) 4);
     System.out.println(oc.occupyof(new OrderHeaderBO()));
     
     }
     //这8个方法不写不行,否则occupyof(int x)会自动重载到occupyof(Object o),并且无法在方法中判断
     public static int occupyof(boolean variable) {
       return 1;
     }
     
     public static int occupyof(byte variable) {
       return 1;
     }
     
     public static int occupyof(short variable) {
       return 2;
     }
     
     public static int occupyof(char variable) {
       return 2;
     }
     
     public static int occupyof(int variable) {
       return 4;
     }
     
     public static int occupyof(float variable) {
       return 4;
     }
     
     public static int occupyof(long variable) {
       return 8;
     }
     
     public static int occupyof(double variable) {
       return 8;
     }
     
     public Occupy(byte nullReferenceSize, byte emptyObjectSize, byte emptyArrayVarSize) {
       this.NULL_REFERENCE_SIZE = nullReferenceSize;
       this.EMPTY_OBJECT_SIZE = emptyObjectSize;
       this.EMPTY_ARRAY_VAR_SIZE = emptyArrayVarSize;
     }
     
     public static Occupy forJRockitVM() {
       return new Occupy((byte) 4, (byte) 8, (byte) 8);
     }
     
     public static Occupy forSun32BitsVM() {
       return new Occupy((byte) 4, (byte) 8, (byte) 4);
     }
     
     public static Occupy forSun64BitsVM() {
       return new Occupy((byte) 8, (byte) 16, (byte) 8);
     }
     
     public static Occupy forDetectedVM(){
       return null;
     }
     
     private final byte NULL_REFERENCE_SIZE;
     private final byte EMPTY_OBJECT_SIZE;
     private final byte EMPTY_ARRAY_VAR_SIZE;
     
     private static class ref{
       public ref(Object obj){
         this.obj = obj;
       }
       final Object obj;
       @Override
       public boolean equals(Object obj) {
         return (obj instanceof ref) && ((ref)obj).obj == this.obj;
       }
       @Override
       public int hashCode() {
         return obj.hashCode();
       }
     }
     
     private List dedup = new ArrayList();
     
     public int occupyof(Object object){
       dedup.clear();
       return occupyof0(object);
     }
     private int occupyof0(Object object) {
       if (object == null)
         return 0;
       ref r = new ref(object);
       if(dedup.contains(r))
         return 0;
       dedup.add(r);
       int varSize = 0;//对象中的值类型、引用类型变量大小
       int objSize = 0;//对象中的引用类型指向的对象实例的大小
       for (Class clazz = object.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
    //      System.out.println(clazz);
         if (clazz.isArray()) {//当前对象的数组
           varSize += EMPTY_ARRAY_VAR_SIZE;
           Class<?> componentType = clazz.getComponentType();
           if (componentType.isPrimitive()) {//当前数组是原生类型的数组
             varSize += lengthOfPrimitiveArray(object) * sizeofPrimitiveClass(componentType);
             return occupyOfSize(EMPTY_OBJECT_SIZE, varSize, 0);
           }
           Object[] array = (Object[]) object;
           varSize += NULL_REFERENCE_SIZE * array.length;//当前数组有length个引用,每个占用4字节
           for (Object o : array)
             objSize += occupyof0(o);
           return occupyOfSize(EMPTY_OBJECT_SIZE, varSize, objSize);
         }
         Field[] fields = clazz.getDeclaredFields();
         for (Field field : fields) {
           if (Modifier.isStatic(field.getModifiers()))
             continue;//类成员不计
           //System.out.println(field.getDeclaringClass());
           if(clazz != field.getDeclaringClass())
             continue;
           Class<?> type = field.getType();
           if (type.isPrimitive())
             varSize += sizeofPrimitiveClass(type);
           else {
             varSize += NULL_REFERENCE_SIZE;//一个引用型变量占用4个字节
             try {
               field.setAccessible(true);//可以访问非public类型的变量
                 objSize += occupyof0(field.get(object));
             } catch (Exception e) {
               objSize += occupyofConstructor(object, field);
             }
           }
         }
       }
       return occupyOfSize(EMPTY_OBJECT_SIZE, varSize, objSize);
     }
     
     public static int sizeof(boolean variable) {
       return 1;
     }
     
     public static int sizeof(byte variable) {
       return 1;
     }
     
     public static int sizeof(short variable) {
       return 2;
     }
     
     public static int sizeof(char variable) {
       return 2;
     }
     
     public static int sizeof(int variable) {
       return 4;
     }
     
     public static int sizeof(float variable) {
       return 4;
     }
     
     public static int sizeof(long variable) {
       return 8;
     }
     
     public static int sizeof(double variable) {
       return 8;
     }
     
     
     public int sizeof(Object object) {
       if (object == null)
         return 0;
       int size = EMPTY_OBJECT_SIZE;
       Class clazz = object.getClass();
       if (clazz.isArray()) {
         size += EMPTY_ARRAY_VAR_SIZE;//length变量是int型
         Class<?> componentType = clazz.getComponentType();
         if (componentType.isPrimitive())
           return size + lengthOfPrimitiveArray(object) * sizeofPrimitiveClass(componentType);
         Object[] array = (Object[]) object;
         size += 4 * array.length;
         for (Object o : array)
           size += sizeof(o);
         return size;
       }
       Field[] fields = clazz.getDeclaredFields();
       for (Field field : fields) {
         if (Modifier.isStatic(field.getModifiers()))
           continue;//类成员不计
         Class<?> type = field.getType();
         if (type.isPrimitive())
           size += sizeofPrimitiveClass(type);
         else {
           size += 4;//一个引用型变量占用4个字节
           try {
             field.setAccessible(true);//可以访问非public类型的变量
             size += sizeof(field.get(object));
           } catch (Exception e) {
             size += sizeofConstructor(object, field);
           }
         }
       }
       return size;
     }
     
     private static int occupyofConstructor(Object object, Field field) {
       throw new UnsupportedOperationException("field type Constructor not accessible: " + object.getClass() + " field:" + field);
     }
     
     private static int sizeofConstructor(Object object, Field field) {
       throw new UnsupportedOperationException("field type Constructor not accessible: " + object.getClass() + " field:" + field);
     }
     
     
     private static int occupyOfSize(int size) {
       return (size + 7) / 8 * 8;
     }
     
     private static int occupyOfSize(int selfSize, int varsSize, int objsSize) {
    //    System.out.println("self=" + selfSize + " vars=" + varsSize + " objs=" + objsSize);
       return occupyOfSize(selfSize) + occupyOfSize(varsSize) + objsSize;
     }
     
     private static int sizeofPrimitiveClass(Class clazz) {
       return clazz == boolean.class || clazz == byte.class ? 1 : clazz == char.class || clazz == short.class ? 2 : clazz == int.class || clazz == float.class ? 4
           : 8;
     }
     
     private static int lengthOfPrimitiveArray(Object object) {
       Class<?> clazz = object.getClass();
       return clazz == boolean[].class ? ((boolean[]) object).length : clazz == byte[].class ? ((byte[]) object).length
           : clazz == char[].class ? ((char[]) object).length : clazz == short[].class ? ((short[]) object).length
               : clazz == int[].class ? ((int[]) object).length : clazz == float[].class ? ((float[]) object).length
                   : clazz == long[].class ? ((long[]) object).length : ((double[]) object).length;
     }
    }

    展开全文
  • 记一次java项目占用内存过大,导致项目无限重启情况. 内存一直增加,并且不释放,就...2.查询后会获得一个PID线程,使用jmap -histopid可以查看当前Java进程创建的对象数目和占用内存大小 jmap -histo:live...

    记一次java项目占用内存过大,导致项目无限重启的情况.

     

    内存一直增加,并且不释放,就导致了服务器一直处在宕机的状态下,简单记录一下定位问题的几个关键知识点.

     

    1.使用top命令查询占用内存和cpu较大的线程

     

    2.查询后会获得一个PID的线程,使用jmap -histo pid 可以查看当前Java进程创建的对象数目和占用内存大小

    jmap -histo:live [pid] 还有一个查询活跃对象的,这个命令执行以后,会执行一次GC的操作

     

    3.jmap -dump:live,format=b,file=xxx.xxx [pid]  使用这个命令可以导出堆栈的信息,以便于我们具体分析问题

    导出来以后需要利用Eclipse Memory Analyzer Tool(MAT)分析内存泄漏,MAT工具大家可以自行在百度上搜索下载即可.

    简单看一下这个工具的用途:

    这是导入堆栈信息之后的MAT界面,首先是一个overview,红框里面的基本上就是我们要使用到的.

    点击report下面的Leak Suspects,MAT工具会列出来一个异常的报告,大家可以根据这个来分析问题

    detail里面可以看到比较详细的链路信息

    org.hibernate.internal.SessionFactoryImpl这个类,查询数据映射到map的数据结构上,但是这个数据是hibernate的缓存数据,我们并不会直接使用的.

    点到detail里面可以看到:

    这个是累计对象数量,从这里我们就可以看出来是Hibernate的缓存计划导致的.

    解决方案可以参考https://hibernate.atlassian.net/browse/HHH-5300

     

    最终的解决方案:

    设置缓存最大值,而不是采用hibernate默认的值,就可以解决问题.

    spring:
      jpa:
        properties:
          hibernate:
            query:
              plan_cache_max_size: 64
              plan_parameter_metadata_max_size: 32
              plan_cache_max_soft_references: 1024
              plan_cache_max_strong_references: 64

    展开全文
  • Java内存分析工具MAT

    2019-05-07 19:26:31
    使用起来非常方便,尤其是在分析大内存的dump文件时,可以非常直观的看到各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系、利用OQL对象查询,以及可以很方便的找出对象GC Roots的相关信息,当然最...
  • jmap查询JVM堆内存

    2020-12-02 23:34:40
    jmap命令可以获取运行中的jvm的快照,从而离线分析,检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中最多的对象,各种对象所占用的内存大小.可以使用jmap生成Heap Dump. 什么是堆Dump 堆Dump是反应Java...
  • java内存监控(下)

    2019-07-21 22:37:30
    jhat用于分析产生的堆文件,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。 1、导出堆文件: jmap -dump:live,file=E:\heap.log pid C:\Users\WWH>jmap -dump:live,file...
  • 因为在内存中,数组对象被创建时,是被分配了一块连续的内存地址,这块连续的内存地址上,存放着大小相等的引用类型,在默认情况下,如果虚拟机内存没有超过32GB,那么JVM使用的是32位的压缩指针,也就是说,在这块...
  • 使用起来非常方便,尤其是在分析大内存的dump文件时,可以非常直观的看到各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系、利用OQL对象查询,以及可以很方便的找出对象GC Roots的相关信息,当然最...
  • Lab5 在MAT内使用OQL查询内存导出

    千次阅读 2019-05-29 17:46:59
    CircularOrbit 所有对象实例;...PhysicalObject(及其子类)的对象实例数量和总占用内存大小 所有包含元素数量大于 100 Collections 实例 更多参考:http://cr.openjdk.java.net/~sundar/8...
  • javahashmap

    千次阅读 2020-06-18 13:03:57
    线性表:存储在连续的内存地址,查询快,插入和删除慢。 链式表:存储在间断的,大小不固定,插入和删除快,但是查询的速度慢。 hashmap是以上两种者折中的解决方案,插入或者删除只需要动一部分即可。 HashMap的...
  • java源码包---java 源码 大量 实例

    千次下载 热门讨论 2013-04-18 23:15:26
     Java生成密钥、保存密钥实例源码,通过本源码可以了解到Java如何产生单钥加密密钥(myKey)、产生双钥密钥对(keyPair)、如何保存公钥字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
  • HQL语句查询借据号——逾期金额信息,借据号重复率低,导致map维护key(借据号)-value(逾期金额信息)的内存超过了JVM配置的map进程内存大小限制,从而内存溢出。 【原因】 对于group by语句,在MR中,当...
  • Tomcat服务器出现java.lang.OutOfMemoryError:Java heap space异常 ... 若同时处理数据量较大:如较大的查询结果或打开较大文件,可能会出现堆内存不足问题 jvm默认堆内存为64M,通过配置改变默认堆的大小 ...
  • java源码包2

    千次下载 热门讨论 2013-04-20 11:28:17
     Java生成密钥、保存密钥实例源码,通过本源码可以了解到Java如何产生单钥加密密钥(myKey)、产生双钥密钥对(keyPair)、如何保存公钥字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
  •  GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...
  • 针对大键和值进行了优化,特别是针对对象的增量维护(就地更新)。 与流行的 Java ConcurrentNavigableMap 相比,它通过额外的 CPU 内核速度更快,扩展性更好。 为什么选择橡树地图? OakMap 提供了出色的性能:它...
  • java源码包3

    千次下载 热门讨论 2013-04-20 11:30:13
     Java生成密钥、保存密钥实例源码,通过本源码可以了解到Java如何产生单钥加密密钥(myKey)、产生双钥密钥对(keyPair)、如何保存公钥字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
  • java源码包4

    千次下载 热门讨论 2013-04-20 11:31:44
     Java生成密钥、保存密钥实例源码,通过本源码可以了解到Java如何产生单钥加密密钥(myKey)、产生双钥密钥对(keyPair)、如何保存公钥字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
  • java面试题

    2018-01-01 15:35:15
    71.5. Hibernate 中Java对象的状态 58 71.5.1. 临时状态 (transient) 58 71.5.2. 持久化状态(persisted) 58 71.5.3. 游离状态(detached) 58 71.5.4. hibernate的三种状态之间如何转换 59 71.6. Hibernate并发机制,...
  •  jhat用于对JAVA heap进行...jhat是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。 第一步:导出堆 第二步:分析堆文件 第三步:查看h...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
     Java生成密钥、保存密钥实例源码,通过本源码可以了解到Java如何产生单钥加密密钥(myKey)、产生双钥密钥对(keyPair)、如何保存公钥字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
  • java面试宝典

    2013-02-28 16:04:01
    java面试试题 全面 准确 带答案 ...245、 如何给weblogic指定大小的内存? 56 246、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 57 247、如何启动时不需输入用户名与密码? 57 248、在...
  • java面试题典 java 面试题 经典

    热门讨论 2010-06-18 13:42:36
    2. 如何给weblogic指定大小的内存? 40 3. 如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 40 4. 如何启动时不需输入用户名与密码? 40 5. 在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行...
  • 密钥 Java生成密钥、保存密钥实例源码,通过本源码可以了解到Java如何产生单钥加密密钥(myKey)、产生双钥密钥对(keyPair)、如何保存公钥字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存...
  • java 面试题 总结

    2009-09-16 08:45:34
     GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...
  • JAVA 3D动画演示

    2009-07-31 16:07:04
    这些模式降低了存储结构图像的内存大小,因为Java 3D避免将图像从应用空间拷贝到图形内存. 在Windows OS环境下,使用OpenGL作为Java 3D优先图像引擎,ImageComponent2D格式应是ImageComponent2D.FORMAT_RGB,...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 155
精华内容 62
关键字:

查询java对象的内存大小

java 订阅