`
teasp
  • 浏览: 61551 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

实现一个sizeof获取Java对象大小

阅读更多

   由于Java的设计者不想让程序员管理和了解内存的使用,我们想要知道一个对象在内存中的大小变得比较困难了。本文提供了可以获取对象的大小的方法,但是由于各个虚拟机在内存使用上可能存在不同,因此该方法不能在各虚拟机上都适用,而是仅在hotspot 32位虚拟机上,或者其它内存管理方式与hotspot 32位虚拟机相同的虚拟机上 适用。

 

    本方法使用了Unsafe类来访问对象的私有属性,因此有些特殊的设置和做法,要留意类定义前面的文字说明。

 

    要想计算对象大小,我们必须熟悉hotspot32上不同类型所占的空间:

一,原始类型primitives:

    boolean:1 byte,尽管Java语言规范里面boolean是一个bit;

    byte:1 byte;

    char:2 bytes;

    short:2 bytes;

    int:4 bytes;

    float:4 bytes;

    long:8 bytes;

    double:8 bytes。

二,引用类型:

    4 bytes,即使是null值也是如此。

三,空的普通对象(无任何属性,如new Object(),不是null对象):

    8 bytes。存放对象头的各种信息。

四,空的数组(即长度为0的数组,而不是null数组):

    12 bytes,其中比普通对象多出来的4 bytes是用来放数组长度的。

五,hotspot 32分配内存是以8 bytes的整数倍来计算的,因此不足8个字节的对象要补足剩余的字节数以对齐。

 

/**
 * 这个例子在eclipse里不能直接编译,要到项目的属性,
 * Java Compiler,Errors/Warnings中Deprecated and restricted API
 * 中Forbidden reference(access rules)中设置为warning。
 * 
 * 获取一个Java对象在内存所占的空间,不同的虚拟机内存管理方式可能不同,
 * 本例是针对32位的hotspot虚拟机的。
 * 
 * 由于虚拟机对字符串做了特殊处理,比如将其放入常量池,因此sizeof得到的字符串
 * 包含了常量池里面占用的空间。基本类型的包装类也会重复利用对象。
 * 
 * 设计作者: teasp
 * 信息描述:
 */
@SuppressWarnings("restriction")
public class HotspotSizeof
{
    public static final int OBJ_BASIC_LEN = 8 * 8;
    public static final int ARRAY_BASIC_LEN = 12 * 8;
    public static final int OBJ_REF_LEN = 4 * 8;
    
    public static final int ALIGN = 8 * 8;
    
    private static Unsafe UNSAFE;
    
    static {
        try
        {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);  
            UNSAFE = (Unsafe) theUnsafe.get(null); 
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }  
    }
    
    /**
     * 原始类型的种类,以及每个类型所占空间,单位为bit
     * @author Administrator
     *
     */
    private enum PType 
    {
        布尔(8)/*Java语言规定是1个bit*/,字节(8),字符(16),短整(16),
        整形(32),浮点(32),长整(64),双精(64);
        
        private int bits;
        
        private PType(int bits)
        {
            this.bits = bits;
        }
        
        public int getBits() {
            return bits;
        }
    }
    
    /**
     * 计算obj对象在虚拟机中所占的内存,单位为bit。
     * 如果isPapa为true,则表明计算的是obj对象父类定义的属性。
     * 
     * @param obj
     * @param clazz
     * @param isPapa
     * @return
     */
    private static int getObjBits(Object obj, Class<?> clazz, boolean isPapa) 
    {
        int bits = 0;
        if (obj == null)
        {
            return bits;
        }
        
        bits += OBJ_BASIC_LEN;
        if (isPapa)
        {
            bits = 0;
        }
        
        Field[] fields = clazz.getDeclaredFields();
        if (fields != null) 
        {
            for (Field field : fields) 
            {
                //静态属性不参与计算
                if (Modifier.isStatic(field.getModifiers()))
                {
//                    System.out.println("static " + field.getName());
                    continue;
                }
                Class<?> c = field.getType();
                 if (c == boolean.class)
                 {
                     bits += PType.布尔.getBits();
                 }
                 else if (c == byte.class)
                 {
                     bits += PType.字节.getBits();
                 }
                 else if (c == char.class)
                 {
                     bits += PType.字符.getBits();
                 }
                 else if (c == short.class)
                 {
                     bits += PType.短整.getBits();
                 }
                 else if (c == int.class)
                 {
                     bits += PType.整形.getBits();
                     System.out.println(field.getName() + "=" + UNSAFE.getInt(obj, UNSAFE.objectFieldOffset(field)));
                 }
                 else if (c == float.class)
                 {
                     bits += PType.浮点.getBits();
                 }
                 else if (c == long.class)
                 {
                     bits += PType.长整.getBits();
                 }
                 else if (c == double.class)
                 {
                     bits += PType.双精.getBits();
                 }
                 else if (c == void.class)
                 {
                     //nothing
                 } else if (c.isArray())
                 {//是数组
                     Object o = UNSAFE.getObject(obj, UNSAFE.objectFieldOffset(field));
                     bits += OBJ_REF_LEN;
                     if (o != null)
                     {
                         try
                         {
                             bits += bitsofArray(o);
                         } catch (Exception e)
                         {
                             throw new RuntimeException(e);
                         }
                     }
                 } else 
                 {//普通对象
                     Object o = UNSAFE.getObject(obj, UNSAFE.objectFieldOffset(field));
                     bits += OBJ_REF_LEN;
                     if (o != null) 
                     {
                         try
                         {
                             bits += bitsof(o);
                         } catch (Exception e)
                         {
                             throw new RuntimeException(e);
                         }
                     }
                 }
            }
        }
        
        Class<?> papa = clazz.getSuperclass();
        if (papa != null)
        {
           bits += getObjBits(obj, papa, true); 
        }
        
        //补齐,当计算父类属性时,因为是对同一个对象在进行统计,所以不要补齐。
        //一个对象只做一次补齐动作。
        if (false == isPapa)
        {
            if (bits%ALIGN > 0)
            {
                bits += (ALIGN - bits%ALIGN);
            }
        }
        
        return bits;
    }
    
    /**
     * 计算arr数组在虚拟机中所占的内存,单位为bit
     * @param arr
     * @return
     */
    private static int bitsofArray(Object arr)
    {
        int bits = 0;
        if (arr == null)
        {
            return bits;
        }
        
        bits += ARRAY_BASIC_LEN;
        
        Class<?> c = arr.getClass();
        if (c.isArray() == false)
        {
            throw new RuntimeException("Must be array!");
        }
        
        if (c == boolean[].class)
        {
            bits += PType.布尔.getBits() * ((boolean[])arr).length;
        }
        else if (c == byte[].class)
        {
            bits += PType.字节.getBits() * ((byte[])arr).length;
        }
        else if (c == char[].class)
        {
            bits += PType.字符.getBits() * ((char[])arr).length;
        }
        else if (c == short[].class)
        {
            bits += PType.短整.getBits() * ((short[])arr).length;
        }
        else if (c == int[].class)
        {
            bits += PType.整形.getBits() * ((int[])arr).length;
        }
        else if (c == float[].class)
        {
            bits += PType.浮点.getBits() * ((float[])arr).length;
        }
        else if (c == long[].class)
        {
            bits += PType.长整.getBits() * ((long[])arr).length;
        }
        else if (c == double[].class)
        {
            bits += PType.双精.getBits() * ((double[])arr).length;
        }
        else
        {
            Object[] os = (Object[])arr;
            for (Object o : os)
            {
                bits += OBJ_REF_LEN + bitsof(o);
            }
        }
        
        //补齐
        if (bits%ALIGN > 0)
        {
            bits += (ALIGN - bits%ALIGN);
        }
        
        return bits;
    }
    
    /**
     * 计算obj对象在虚拟机中所占的内存,单位为bit
     * @param obj
     * @return
     */
    private static int bitsof(Object obj)
    {
        if (obj == null)
        {
            return 0;
        }
        
        if (obj.getClass().isArray())
        {
            return bitsofArray(obj);
        }
        
        return getObjBits(obj, obj.getClass(), false);
    }
    
    /**
     * 计算obj对象在虚拟机中所占的内存,单位为byte
     * @param obj
     * @return
     */
    public static int sizeof(Object obj)
    {
        return bitsof(obj)/8;
    }
    
    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)
        {
            Runtime.getRuntime().runFinalization();
            Runtime.getRuntime().gc();
            Thread.yield();
            
            usedMem2 = usedMem1;
            usedMem1 = usedMemory();
        }
    }
    
    private static long usedMemory()
    {
        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    }
    
    /**
     * 本方法在计算String以及原始类型的包装类的时候可能不准。
     * String s = "abc"; 这种方式产生的String对象会被放入常量池。
     * Integer.valueOf(1)会返回缓存的对象而不是new一个。
     * @param cls
     * @return
     * @throws Exception
     */
    private static long determinObjSize(Class<?> cls) 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 = cls.newInstance();
            
            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;
        
        return size;
    }
    
    public static void main(String[] args)
    {
        HotspotSizeof hs = new HotspotSizeof();
        hs.test();
    }
    
    @Test
    public void test() 
    {
        try
        {
            Assert.assertEquals(determinObjSize(Obj4SizeofTest.class), sizeof(new Obj4SizeofTest()));
        } catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }
}

 

 

测试用的两个类:

/**
 * 设计作者: teasp
 * 信息描述:
 */
public class Papa
{
    @SuppressWarnings("unused")
    private int aint = 4;
    public static int bint;
    @SuppressWarnings("unused")
//    private String str = "123";
//    private String str = new String("123");
//    private String str = new String(new byte[]{49,50,51});
    private String str = new String(new char[]{49,50,51});
    @SuppressWarnings("unused")
    private int[] ints = {};
    @SuppressWarnings("unused")
    private int[][] intss = {{}};
//    private int[][] intss = {{1},{1,2}};
}


/**
 * 设计作者: teasp
 * 信息描述:
 */
public class Obj4SizeofTest extends Papa
{
    @SuppressWarnings("unused")
    private int aint = 3;
    public int bint = 4;
    @SuppressWarnings("unused")
    private boolean b1 = true;
    @SuppressWarnings("unused")
    private boolean b2 = true;
    @SuppressWarnings("unused")
    private boolean b3 = true;
    @SuppressWarnings("unused")
    private boolean b4 = true;
    @SuppressWarnings("unused")
    private boolean b5 = true;
    @SuppressWarnings("unused")
    private boolean b6 = true;
    @SuppressWarnings("unused")
    private boolean b7 = true;
    @SuppressWarnings("unused")
    private boolean b8 = true;
    @SuppressWarnings("unused")
    private String str1;
    @SuppressWarnings("unused")
    private Object obj = new Papa();
    public static final byte[] bytes = {97};
    @SuppressWarnings("unused")
    private String str2 = new String(bytes);
    @SuppressWarnings("unused")
    private Integer i = new Integer(1);
    @SuppressWarnings("unused")
    private int[] is = {1,2,3};
    @SuppressWarnings("unused")
    private Object[][] objs = {{new Object(),new Object()},{new Object(),new Object()}};
}

 

0
5
分享到:
评论
10 楼 beowulf2005 2013-05-23  
反射这勾当,本来就有点半黑不白的味道。

在没有SecurityManager的情况下,
setAccess(true);
大多数情况下,可以取到你想要的各种private的,protected的字段,甚至方法和构造方法。

在使用Spring初始化Bean的时候,很多时候就是写private的构造器,让Spring通过反射调用,从而避免外部用户调用Bean构造器。

SecurityManager需要在JVM启动时给定。
Java Security,是个复杂的题目,就不展开了。


9 楼 teasp 2013-05-18  
finallygo 写道
teasp 写道
beowulf2005 写道

teasp 写道
beowulf2005 写道
通过反射获取每个对象的Field就可以达到目的了,
为什么用Unsafe?

另外还得考虑一下循环引用的问题,否则可能死循环


如果通过反射的话,怎么获取私有属性的值呢?用unsafe的目的就是为了获取私有属性的值。

循环引用是个问题,暂时先不考虑它。


http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

public Field[] getDeclaredFields()
                          throws SecurityException
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if the class or interface declares no fields, or if this Class object represents a primitive type, an array class, or void.
See The Java Language Specification, sections 8.2 and 8.3.

Returns:
the array of Field objects representing all the declared fields of this class
Throws:
SecurityException - If a security manager, s, is present and any of the following conditions is met:
invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared fields within this class
the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class
Since:
JDK1.1



如果我没搞错的话,这个方法只是返回声明的所有属性,但是你得不到属性的值。

field可以setAccess(true),这样就可以获取值了

可以。之前很少用反射,我的例子确实弄复杂了。不过我很奇怪,既然可以通过反射获取私有变量的值,那私有的意义岂不是被破坏了呢?
8 楼 teasp 2013-05-18  
finallygo 写道
teasp 写道
beowulf2005 写道

teasp 写道
beowulf2005 写道
通过反射获取每个对象的Field就可以达到目的了,
为什么用Unsafe?

另外还得考虑一下循环引用的问题,否则可能死循环


如果通过反射的话,怎么获取私有属性的值呢?用unsafe的目的就是为了获取私有属性的值。

循环引用是个问题,暂时先不考虑它。


http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

public Field[] getDeclaredFields()
                          throws SecurityException
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if the class or interface declares no fields, or if this Class object represents a primitive type, an array class, or void.
See The Java Language Specification, sections 8.2 and 8.3.

Returns:
the array of Field objects representing all the declared fields of this class
Throws:
SecurityException - If a security manager, s, is present and any of the following conditions is met:
invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared fields within this class
the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class
Since:
JDK1.1



如果我没搞错的话,这个方法只是返回声明的所有属性,但是你得不到属性的值。

field可以setAccess(true),这样就可以获取值了



非常感谢,我试试。
7 楼 finallygo 2013-05-18  
teasp 写道
beowulf2005 写道

teasp 写道
beowulf2005 写道
通过反射获取每个对象的Field就可以达到目的了,
为什么用Unsafe?

另外还得考虑一下循环引用的问题,否则可能死循环


如果通过反射的话,怎么获取私有属性的值呢?用unsafe的目的就是为了获取私有属性的值。

循环引用是个问题,暂时先不考虑它。


http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

public Field[] getDeclaredFields()
                          throws SecurityException
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if the class or interface declares no fields, or if this Class object represents a primitive type, an array class, or void.
See The Java Language Specification, sections 8.2 and 8.3.

Returns:
the array of Field objects representing all the declared fields of this class
Throws:
SecurityException - If a security manager, s, is present and any of the following conditions is met:
invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared fields within this class
the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class
Since:
JDK1.1



如果我没搞错的话,这个方法只是返回声明的所有属性,但是你得不到属性的值。

field可以setAccess(true),这样就可以获取值了
6 楼 teasp 2013-05-17  
beowulf2005 写道

teasp 写道
beowulf2005 写道
通过反射获取每个对象的Field就可以达到目的了,
为什么用Unsafe?

另外还得考虑一下循环引用的问题,否则可能死循环


如果通过反射的话,怎么获取私有属性的值呢?用unsafe的目的就是为了获取私有属性的值。

循环引用是个问题,暂时先不考虑它。


http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

public Field[] getDeclaredFields()
                          throws SecurityException
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if the class or interface declares no fields, or if this Class object represents a primitive type, an array class, or void.
See The Java Language Specification, sections 8.2 and 8.3.

Returns:
the array of Field objects representing all the declared fields of this class
Throws:
SecurityException - If a security manager, s, is present and any of the following conditions is met:
invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared fields within this class
the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class
Since:
JDK1.1



如果我没搞错的话,这个方法只是返回声明的所有属性,但是你得不到属性的值。
5 楼 beowulf2005 2013-05-17  

teasp 写道
beowulf2005 写道
通过反射获取每个对象的Field就可以达到目的了,
为什么用Unsafe?

另外还得考虑一下循环引用的问题,否则可能死循环


如果通过反射的话,怎么获取私有属性的值呢?用unsafe的目的就是为了获取私有属性的值。

循环引用是个问题,暂时先不考虑它。


http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

public Field[] getDeclaredFields()
                          throws SecurityException
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if the class or interface declares no fields, or if this Class object represents a primitive type, an array class, or void.
See The Java Language Specification, sections 8.2 and 8.3.

Returns:
the array of Field objects representing all the declared fields of this class
Throws:
SecurityException - If a security manager, s, is present and any of the following conditions is met:
invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared fields within this class
the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class
Since:
JDK1.1
4 楼 teasp 2013-05-17  
beowulf2005 写道
通过反射获取每个对象的Field就可以达到目的了,
为什么用Unsafe?

另外还得考虑一下循环引用的问题,否则可能死循环


如果通过反射的话,怎么获取私有属性的值呢?用unsafe的目的就是为了获取私有属性的值。

循环引用是个问题,暂时先不考虑它。
3 楼 teasp 2013-05-17  
a11ght 写道
其实我想知道你算出来后怎么验证,怎么确认你算得就是正确的呢?亲~


有测试代码的,也有测对象大小的代码,你仔细看就能发现。
2 楼 beowulf2005 2013-05-17  
通过反射获取每个对象的Field就可以达到目的了,
为什么用Unsafe?

另外还得考虑一下循环引用的问题,否则可能死循环
1 楼 a11ght 2013-05-17  
其实我想知道你算出来后怎么验证,怎么确认你算得就是正确的呢?亲~

相关推荐

    java 通过sizeOf计算一个对象的大小

    如果你不想引入额外的依赖,可以自己编写一个简单的工具类来实现`sizeOf`功能。通常,这涉及到遍历对象的字段并估算每个字段的大小。例如,对于基本类型,我们可以知道它们在内存中的固定大小;对于引用类型,我们...

    java-sizeof-0.0.4:一个查看java对象占用内存大小

    "java-sizeof-0.0.4"是一个用于分析Java对象内存占用的工具,它可以帮助开发者更好地理解对象在运行时的内存消耗。这个工具提供了查看对象实例大小的能力,这对于调试和性能优化非常有用。"java-sizeof-0.0.4"包含三...

    Java之基本数据类型 Sizeof 大小

    在`clazzSize`这个文件名中,我们可以推测这可能是一个与类或者对象大小相关的资源,可能包含了不同数据类型实例化后的内存占用情况。通过分析这样的数据,我们可以更深入地理解Java内存模型,并优化我们的代码以...

    测试java对象占用内存大小的例子

    首先,`SizeOf.java`可能是一个实现自定义内存大小计算的类。在Java中,由于垃圾回收机制的存在,直接获取对象的内存占用并不像C++等语言那样简单。通常,我们可以使用一些工具或API来帮助我们。例如,`sun.misc....

    sizeof 计算出实例的大小

    4. **对齐和填充**:Java对象在内存中是以字节对齐的,可能会有填充来保证内存效率。虽然这不是强制的,但是一些JVM实现可能进行填充。因此,实际大小可能比简单相加所有字段大小要大。 5. **注意事项**:使用反射...

    SizeOf.jar

    SizeOf.jar是一个专门用于计算Java对象内存大小的工具。在Java编程中,了解对象占用的内存大小对于优化程序性能、防止内存泄漏以及理解程序运行时的内存消耗至关重要。这个工具通常由开发者使用,以帮助他们更好地...

    SizeOf_0_2_2.zip_java

    例如,可能存在一个名为`SizeOf`的类,其中包含诸如`sizeof()`这样的静态方法,可以直接传入Java对象来获取其大小。 在Java中,对象的大小不仅包括实例变量的大小,还可能包含对齐填充、对象头信息以及可能的引用...

    Eclipse使用SizeOf.jar工具监测内存占用

    例如,可以通过创建一个包含数组或集合的对象,并使用SizeOf.jar提供的方法来获取其占用的内存大小。 ### 步骤5:查看测试结果 运行上述测试代码后,控制台将显示所测试对象的内存占用大小。通过这种方式,你可以...

    面向对象编程:Java的简单数据类型

    面向对象编程是现代软件开发的核心概念,而Java作为一种流行的面向对象编程语言,其简单数据类型是编程的基础元素。简单数据类型是由编程语言本身定义的基本构建块,用于表示各种数值、字符和逻辑值。在Java中,简单...

    common-22.7.0.zip

    在这个名为"common-22.7.0.zip"的压缩包中,包含了一个名为"sizeof-master"的子目录,这可能是一个关于`sizeof`引擎的源代码库,特别是针对`ehcacheconfigurable sizeof`引擎的实现。 `sizeof`引擎是`ehcache`的一...

    java编程思想读书笔记

    - Java中没有`sizeof`操作符来获取变量或数据类型的大小,因为这些信息在编译时就已经确定,并不需要在运行时动态获取。 - 变量的声明和初始化需要遵循一定的规则,例如静态变量(`static`)在类加载时就会被初始...

    2019年Java题库(学生版).pdf

    **题目**:在Java中,一个类可同时定义许多同名的方法,这种面向对象程序的特性称为 **知识点**: - 这种特性称为**方法重载**(Overloading),允许在一个类中定义多个同名但参数列表不同的方法。 ### 19. 访问...

    如何计算Java对象占用了多少空间?

    在Java编程语言中,直接获取一个对象所占用的内存大小并不像C++那样简单,因为Java没有提供类似于`sizeof`的运算符。然而,我们可以通过理解对象在内存中的布局和分配规则来估算对象的大小。这里我们将深入探讨计算...

    Java复习要背诵的内容.pdf

    JVM是一个在各个操作系统上运行的软件层,它负责解释和执行Java类文件,使得Java程序可以在任何支持JVM的平台上运行,而无需关心底层操作系统的细节。 实例方法是指与类的实例(对象)关联的方法,它们可以通过对象...

    Java语言程序设计基础教程

    - `sizeof`不是Java中的保留关键字,因为Java自动管理内存,不需要显式地获取对象大小。 #### 十、Java控制结构与循环 - **知识点**: - 无限循环:`while (true)` 和 `while (!false)` 均会导致无限循环。 - ...

    java工程师笔试题.pdf

    - sizeof运算符:这是一个在C/C++中用于获取变量或数据类型所占内存大小的运算符。 - 函数与参数:提到了函数(function)和参数(parameters),这是编程中用于实现代码复用和模块化的重要概念。 3. 计算机基础...

    java考试题.pdf

    数组在Java中是固定大小的,如int[] x = new int[10](A)创建了一个长度为10的数组,x[9]默认初始化为0,x[10]是越界的。 浮点数比较时,即使数值相等,不同的对象(如new Float(0.1f))也不相等,因此s==t为false...

    Java面试宝典

    - C/C++ 中的 `sizeof` 关键字在 Java 中不存在,Java 使用 `DataSize` 或 `Array.length` 获取对象或数组大小。 13. **native 方法**: - 用 `native` 关键字标记的方法表示其实现是在非 Java 代码(如 C/C++)...

    Java语言程序设计基础教程习题解答.doc

    3. Java中没有`sizeof`关键字,它是C/C++中的运算符,用于获取变量的大小。在Java中,可以使用`System.out.println(Object.getClass().getSimpleName());`来获取对象的类名。 4. 导致无限循环的语句通常是因为循环...

    java考试题.docx

    - `sizeof`不是一个Java关键字,而是在C/C++中用于获取变量大小的关键字。Java中没有这个关键字,因为内存管理是自动的。 6. **注释符号**: - 单行注释使用`//`,多行注释使用`/* ... */`,文档注释使用`/** ......

Global site tag (gtag.js) - Google Analytics