Get the Size (In Bytes) of an Object on the Heap

Get the size (in bytes) of an object on the heap

One option on Apple platforms, because Swift classes are currently built on top of Objective-C classes there, would be to use the Obj-C runtime function class_getInstanceSize, which gives you the size in bytes of an instance of the class, including any padding.

// on a 64-bit machine (1 word == 8 bytes)...

import Foundation

class C {}
print(class_getInstanceSize(C.self)) // 16 bytes metadata for empty class
// (isa ptr + ref count)

class C1 {
var i = 0
var i1 = 0
var b = false
}

print(class_getInstanceSize(C1.self)) // 40 bytes
// (16 metadata + 24 ivars, 8 for i + 8 for i1 + 1 for b + 7 padding)

Calculate size of Object in Java

You can use the java.lang.instrumentation package.

It has a method that can be used to get the implementation specific approximation of object size, as well as overhead associated with the object.

The answer that Sergey linked has a great example, which I'll repost here, but you should have already looked at from his comment:

import java.lang.instrument.Instrumentation;

public class ObjectSizeFetcher {
private static Instrumentation instrumentation;

public static void premain(String args, Instrumentation inst) {
instrumentation = inst;
}

public static long getObjectSize(Object o) {
return instrumentation.getObjectSize(o);
}
}

Use getObjectSize:

public class C {
private int x;
private int y;

public static void main(String [] args) {
System.out.println(ObjectSizeFetcher.getObjectSize(new C()));
}
}

Source

How can I get size in bytes of an object sent using RMI?

You can solve the problem of limiting the size of serialized objects using a custom FilterOutputStream that:

  1. counts the bytes that are written by the write method calls, and
  2. throws a custom IOException subclass when the count exceeds your limit.

Then put this filter between the ByteArrayOutputStream and the ObjectOutputStream.

This is what the code would look like (not tested!):

    public LimitExceededException extends IOException { ... }

public class LimitingOutputStream extends FilterOutputStream {
private int limit;
private int count;

public LimitingOutputStream(OutputStream out, int limit) {
super(out);
this.limit = limit;
}

@Override
public void write(byte b) throws IOException {
if (count++ > limit) {
throw LimitExceededException(...);
}
super.write(b);
}

@Override
// (This override is not strictly necessary, but it makes it faster)
public void write(byte[] bytes, int from, int size) throws IOException {
if (count += size > limit) {
throw LimitExceededException(...);
}
super.write(bytes, from, size);
}
}

/**
* Return the serialization of `o` in a byte array, provided that it is
* less than `limit` bytes. If it is too big, return `null`.
*/
public byte[] serializeWithLimit(Object o, int limit) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
LimitingOutputStream los = new LimitingOutputStream(bos, limit);
ObjectOutputStream oos = new ObjectOutputStream(los);
oos.writeObject(o);
oos.close();
return bos.toByteArray();
} catch (LimitExceededException e) {
return null;
}
}

Yes, this uses exceptions to "get out" when the limit is exceeded, but this is IMO a good use of exceptions. And I challenge anyone who disagrees with that to come up with a better solution. Put it in another Answer.


By the way, this is REALLY BAD code:

} catch (Exception e) {
return Long.MAX_VALUE;
}

In addition to the IOExceptions that you might expect to be thrown, you are also catching all manner of unchecked exceptions, most of which would be caused by bugs ... that you need to know about:

  1. It is bad practice to catch Exception except when you are trying to do a last-ditch diagnosis.

  2. Whenever you catch unexpected exceptions, be sure to log them so that the stack trace can be recorded (depending on the logger configurations). Or if your application doesn't use a logging framework, then have it call e.printStackTrace().

(And if you wouldn't do this in production code, don't do it into a StackOverflow Question either ... 'cos some copy-and-paste coder might just copy it.)

How to calculate object size from a heap dump?

It depends if the total size is the shalow size or the retained size.

  1. Shallow size

    The shallow size of an object is amount of memory used to store the object itself. The referenced objects are not taken into account.

  2. Retained size

    The retained size of an object is the amount of memory that can be freed when the object is collected by the garbage collector.

How to get memory size of variable?

You can use the unsafe.Sizeof function for this.
It returns the size in bytes, occupied by the value you pass into it.
Here's a working example:

package main

import "fmt"
import "unsafe"

func main() {
a := int(123)
b := int64(123)
c := "foo"
d := struct {
FieldA float32
FieldB string
}{0, "bar"}

fmt.Printf("a: %T, %d\n", a, unsafe.Sizeof(a))
fmt.Printf("b: %T, %d\n", b, unsafe.Sizeof(b))
fmt.Printf("c: %T, %d\n", c, unsafe.Sizeof(c))
fmt.Printf("d: %T, %d\n", d, unsafe.Sizeof(d))
}

Take note that some platforms explicitly disallow the use of unsafe, because it is.. well, unsafe. This used to include AppEngine. Not sure if that is still the case today, but I imagine so.

As @Timur Fayzrakhmanov notes, reflect.TypeOf(variable).Size() will give you the same information. For the reflect package, the same restriction goes as for the unsafe package. I.e.: some platforms may not allow its use.



Related Topics



Leave a reply



Submit