Backend Development 9 min read

How Much Memory Does a Java Object Really Use?

Understanding the actual memory footprint of Java objects—including headers, class pointers, fields, and alignment—reveals hidden waste, and the article provides calculations for Integer objects, arrays, and collections, plus practical guidelines to reduce memory usage by preferring primitive types, smaller fields, and arrays over collections.

macrozheng
macrozheng
macrozheng
How Much Memory Does a Java Object Really Use?

When writing Java code, developers usually focus on business logic rather than the exact memory size of a Java object, unaware that a lot of memory can be wasted unintentionally.

How big is a Java object?

To calculate the precise memory consumption of a Java object, you first need to understand its internal structure.

Java object structure

A Java object on the heap consists of three parts:

Object Header

Class Pointer

Fields

Every ordinary Java object has an object header that records the object's state.

Object layout
Object layout

In a 32‑bit environment the layout differs from a 64‑bit one. Example for 32‑bit:

<code>hash(25)+age(4)+lock(3)=32bit</code>

In a 64‑bit environment:

<code>unused(25+1)+hash(31)+age(4)+lock(3)=64bit</code>

The class pointer points to the object's superclass. On a 32‑bit JVM it occupies 4 bytes; on a 64‑bit JVM it is 4 bytes when compressed oops are enabled (or the heap is < 32 GB), otherwise 8 bytes.

Fields refer to instance fields only; static fields are shared and not counted here.

Example: calculating the size of

java.lang.Integer

on a 32‑bit system.

Object Header (4 bytes) + Class Pointer (4 bytes) = 8 bytes. The only instance field is the integer value:

<code>/**
 * The value of the <code>Integer</code>.
 *
 * @serial
 */
private final int value;</code>

An

int

occupies 4 bytes, so the raw size is 4 + 4 + 4 = 12 bytes. However, Java objects are aligned to 8‑byte boundaries, so 4 bytes of padding are added, resulting in 16 bytes.

Arrays are a special kind of object that include an extra

length

field (an

int

).

For

int[] arr = new int[10];

the heap size is:

<code>4 (object header) + 4 (pointer) + 4 (length) + 4*10 (elements) = 52 bytes → aligned to 56 bytes</code>

Memory‑saving principles

Knowing object memory usage lets us see that a

java.lang.Integer

consumes 16 bytes while a primitive

int

uses only 4 bytes—a 4:1 ratio.

1) Prefer primitive types over wrapper types

When designing database schemas or JavaBeans, choose the smallest suitable primitive type (e.g.,

short

,

byte

,

boolean

) instead of larger wrappers.

For example, a

long

uses 4 bytes more than an

int

. If you have one million

long

values, that’s roughly 4 MB of unnecessary memory.

2) Choose the smallest field type that meets capacity requirements

Consider an

ArrayList

holding ten numbers. Its memory breakdown is:

<code>/**
 * The array buffer into which the elements of the ArrayList are stored.
 */
private transient Object[] elementData;

/**
 * The size of the ArrayList (the number of elements it contains).
 */
private int size;</code>

Object Header (4 bytes) + Pointer (4 bytes) +

size

(4 bytes) +

elementData

array object (12 bytes) + ten

Integer

objects (10 × 16 bytes) = 184 bytes.

Replacing the list with an

int[]

uses 12 bytes for the array object plus 4 × 10 = 52 bytes for the elements, aligned to 56 bytes. The ratio of list to array memory is roughly 184:56 (> 3:1).

3) Prefer arrays over collections when possible

<code>Arrays can store primitive types directly, while collections store only wrapper objects.</code>

If a collection is unavoidable, consider memory‑efficient libraries such as fastutil.

4) Small tricks

Represent timestamps with

long

or

int

instead of

Date

or

String

.

If short strings can be enumerated or represented as ASCII, store them as

long

or

int

.

These tricks depend on the specific data and can be applied aggressively when memory is critical.

Conclusion

Performance and readability often conflict; when memory savings are essential, you may need to sacrifice some readability. The principles above provide practical ways to reduce Java heap usage in real‑world applications.

JavaPerformance Optimizationmemory managementbackend developmentObject Layout
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.