Java에서 객체의 메모리 소비는 얼마입니까?
하나의 속성을 가진 100 개의 속성과 100 개의 속성을 가진 하나의 객체가 사용하는 메모리 공간이 각각 하나의 속성을 가지고 있습니까?
객체에 얼마나 많은 메모리가 할당됩니까?
속성을 추가 할 때 얼마나 많은 공간이 사용됩니까?
Mindprod 는 이것이 대답하기 쉬운 질문이 아니라고 지적합니다.
JVM은 임의의 패딩 또는 오버 헤드로 내부, 빅 또는 리틀 엔디안을 만족시키는 방식으로 데이터를 자유롭게 저장할 수 있지만 프리미티브는 공식적인 크기를 가진 것처럼 작동해야합니다.
예를 들어, JVM 또는 원시 컴파일러는 aboolean[]
와 같은 64 비트 길이의 청크 를 저장하기로 결정할 수 있습니다BitSet
. 프로그램이 동일한 답변을 제공하는 한 귀하에게 말할 필요는 없습니다.
- 스택에 일부 임시 객체를 할당 할 수 있습니다.
- 일부 변수 또는 메소드 호출을 완전히 존재하지 않고 최적화하여 상수로 대체 할 수 있습니다.
- 메소드 또는 루프의 버전을 지정할 수 있습니다. 즉, 각각 특정 상황에 최적화 된 두 가지 버전의 메소드를 컴파일 한 다음 호출 할 버전을 먼저 결정합니다.
물론 하드웨어와 OS에는 멀티 캐시, 온칩 캐시, SRAM 캐시, DRAM 캐시, 일반 RAM 작업 세트 및 디스크의 백업 저장소가 있습니다. 모든 캐시 수준에서 데이터가 복제 될 수 있습니다. 이 모든 복잡성으로 인해 RAM 소비를 매우 대략적으로 예측할 수 있습니다.
측정 방법
Instrumentation.getObjectSize()
객체가 소비 한 스토리지의 추정치를 얻는 데 사용할 수 있습니다 .
실제 객체 레이아웃, 풋 프린트 및 참조 를 시각화 하기 위해 JOL (Java Object Layout) 도구를 사용할 수 있습니다 .
객체 헤더 및 객체 참조
최신 64 비트 JDK에서 객체에는 12 바이트 헤더가 있으며 8 바이트의 배수로 채워져 있으므로 최소 객체 크기는 16 바이트입니다. 32 비트 JVM의 경우 오버 헤드는 8 바이트이며 4 바이트의 배수로 채워집니다. ( Dmitry Spikhalskiy의 답변 , Jayen의 답변 및 JavaWorld 에서)
일반적으로 참조는 32 비트 플랫폼 또는 64 비트 플랫폼에서 최대 4 바이트입니다 -Xmx32G
. 32Gb ( -Xmx32G
) 이상 8 바이트 ( 압축 된 객체 참조를 참조하십시오 .)
결과적으로 64 비트 JVM에는 일반적으로 30-50 % 더 많은 힙 공간이 필요합니다. ( 32 비트 또는 64 비트 JVM을 사용해야합니까? , 2012, JDK 1.7)
박스 타입, 배열 및 문자열
박스형 래퍼는 기본 유형 ( JavaWorld )에 비해 오버 헤드가 있습니다 .
Integer
: 16 바이트 결과는 예상 한 것보다 약간 나쁩니다.int
값이 4 바이트에 불과할 수 있기 때문 입니다. 사용Integer
오버 I는 기본 유형으로 값을 저장할 수있는 경우에 비해 좀 300 %의 메모리를 요한다
Long
: 16 바이트도 : 분명히 힙의 실제 객체 크기는 특정 CPU 유형에 대한 특정 JVM 구현에 의해 수행되는 낮은 수준의 메모리 정렬에 종속됩니다. aLong
는 8 바이트의 Object 오버 헤드와 실제 long 값의 경우 8 바이트가 더 있는 것 같습니다 . 대조적으로,Integer
사용하지 않는 JVM이 8 바이트 단어 경계에서 객체 정렬을 강제하기 때문에 사용되지 않는 4 바이트 구멍이있었습니다.
다른 용기들도 비용이 많이 든다 :
다차원 배열 : 또 다른 놀라움을 제공합니다.
개발자는 일반적으로int[dim1][dim2]
수치 및 과학 컴퓨팅과 같은 구문을 사용 합니다.에서
int[dim1][dim2]
배열 인스턴스, 모든 중첩 된int[dim2]
배열은이다Object
그 자체이다. 각각은 일반적인 16 바이트 배열 오버 헤드를 추가합니다. 삼각형 또는 거친 배열이 필요하지 않은 경우 순수한 오버 헤드를 나타냅니다. 배열 치수가 크게 다를 때 영향이 커집니다.예를 들어,
int[128][2]
인스턴스는 3,600 바이트를 사용합니다.int[256]
인스턴스가 사용 하는 1,040 바이트 (동일 용량)는 3,600 바이트가 246 %의 오버 헤드를 나타냅니다. 의 극단적 인 경우byte[256][1]
오버 헤드 계수는 거의 19입니다! 동일한 구문이 스토리지 오버 헤드를 추가하지 않는 C / C ++ 상황과 비교하십시오.
String
:String
의 메모리 증가는 내부 문자 배열의 증가를 추적합니다. 그러나String
클래스는 또 다른 24 바이트의 오버 헤드를 추가합니다.비어 있지 않은
String
크기가 10 자 이하인 경우 유용한 페이로드 (각 문자에 2 바이트 + 길이에 4 바이트)에 대한 추가 오버 헤드 비용의 범위는 100-400 %입니다.
조정
이 예제 객체를 고려하십시오 .
class X { // 8 bytes for reference to the class definition
int a; // 4 bytes
byte b; // 1 byte
Integer c = new Integer(); // 4 bytes for a reference
}
순진 합계는 인스턴스가 X
17 바이트를 사용함을 나타냅니다. 그러나 정렬 (패딩이라고도 함)으로 인해 JVM은 8 바이트의 배수로 메모리를 할당하므로 17 바이트 대신 24 바이트를 할당합니다.
아키텍처 / jdk에 따라 다릅니다. 최신 JDK 및 64 비트 아키텍처의 경우 객체에는 12 바이트 헤더와 8 바이트 패딩이 있으므로 최소 객체 크기는 16 바이트입니다. Java Object Layout 이라는 도구 를 사용하여 크기를 결정하고 엔티티의 오브젝트 레이아웃 및 내부 구조에 대한 세부 사항을 얻거나 클래스 참조로이 정보를 추측 할 수 있습니다. 내 환경에서 정수의 출력 예 :
Running 64-bit HotSpot VM.
Using compressed oop with 3-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
java.lang.Integer object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int Integer.value N/A
Instance size: 16 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
따라서 Integer의 경우 인스턴스 크기는 16 바이트입니다. 헤더 바로 다음과 패딩 경계 바로 앞에 4 바이트 int가 압축되기 때문입니다.
코드 샘플 :
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.util.VMSupport;
public static void main(String[] args) {
System.out.println(VMSupport.vmDetails());
System.out.println(ClassLayout.parseClass(Integer.class).toPrintable());
}
maven을 사용하는 경우 JOL을 얻으려면 다음을 수행하십시오.
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.3.2</version>
</dependency>
Each object has a certain overhead for its associated monitor and type information, as well as the fields themselves. Beyond that, fields can be laid out pretty much however the JVM sees fit (I believe) - but as shown in another answer, at least some JVMs will pack fairly tightly. Consider a class like this:
public class SingleByte
{
private byte b;
}
vs
public class OneHundredBytes
{
private byte b00, b01, ..., b99;
}
On a 32-bit JVM, I'd expect 100 instances of SingleByte
to take 1200 bytes (8 bytes of overhead + 4 bytes for the field due to padding/alignment). I'd expect one instance of OneHundredBytes
to take 108 bytes - the overhead, and then 100 bytes, packed. It can certainly vary by JVM though - one implementation may decide not to pack the fields in OneHundredBytes
, leading to it taking 408 bytes (= 8 bytes overhead + 4 * 100 aligned/padded bytes). On a 64 bit JVM the overhead may well be bigger too (not sure).
EDIT: See the comment below; apparently HotSpot pads to 8 byte boundaries instead of 32, so each instance of SingleByte
would take 16 bytes.
Either way, the "single large object" will be at least as efficient as multiple small objects - for simple cases like this.
No, registering an object takes a bit of memory too. 100 objects with 1 attribute will take up more memory.
It appears that every object has an overhead of 16 bytes on 32-bit systems (and 24-byte on 64-bit systems).
http://algs4.cs.princeton.edu/14analysis/ is a good source of information. One example among many good ones is the following.
http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf is also very informative, for example:
Is the memory space consumed by one object with 100 attributes the same as that of 100 objects, with one attribute each?
No.
How much memory is allocated for an object?
- The overhead is 8 bytes on 32-bit, 12 bytes on 64-bit; and then rounded up to a multiple of 4 bytes (32-bit) or 8 bytes (64-bit).
How much additional space is used when adding an attribute?
- Attributes range from 1 byte (byte) to 8 bytes (long/double), but references are either 4 bytes or 8 bytes depending not on whether it's 32bit or 64bit, but rather whether -Xmx is < 32Gb or >= 32Gb: typical 64-bit JVM's have an optimisation called "-UseCompressedOops" which compress references to 4 bytes if the heap is below 32Gb.
The total used / free memory of an program can be obtained in the program via
java.lang.Runtime.getRuntime();
The runtime has several method which relates to the memory. The following coding example demonstrate its usage.
package test;
import java.util.ArrayList;
import java.util.List;
public class PerformanceTest {
private static final long MEGABYTE = 1024L * 1024L;
public static long bytesToMegabytes(long bytes) {
return bytes / MEGABYTE;
}
public static void main(String[] args) {
// I assume you will know how to create a object Person yourself...
List < Person > list = new ArrayList < Person > ();
for (int i = 0; i <= 100000; i++) {
list.add(new Person("Jim", "Knopf"));
}
// Get the Java runtime
Runtime runtime = Runtime.getRuntime();
// Run the garbage collector
runtime.gc();
// Calculate the used memory
long memory = runtime.totalMemory() - runtime.freeMemory();
System.out.println("Used memory is bytes: " + memory);
System.out.println("Used memory is megabytes: " + bytesToMegabytes(memory));
}
}
I've gotten very good results from the java.lang.instrument.Instrumentation approach mentioned in another answer. For good examples of its use, see the entry, Instrumentation Memory Counter from the JavaSpecialists' Newsletter and the java.sizeOf library on SourceForge.
The question will be a very broad one.
It depends on the class variable or you may call as states memory usage in java.
It also has some additional memory requirement for headers and referencing.
The heap memory used by a Java object includes
memory for primitive fields, according to their size (see below for Sizes of primitive types);
memory for reference fields (4 bytes each);
an object header, consisting of a few bytes of "housekeeping" information;
Objects in java also requires some "housekeeping" information, such as recording an object's class, ID and status flags such as whether the object is currently reachable, currently synchronization-locked etc.
Java object header size varies on 32 and 64 bit jvm.
Although these are the main memory consumers jvm also requires additional fields sometimes like for alignment of the code e.t.c.
Sizes of primitive types
boolean & byte -- 1
char & short -- 2
int & float -- 4
long & double -- 8
In case it's useful to anyone, you can download from my web site a small Java agent for querying the memory usage of an object. It'll let you query "deep" memory usage as well.
no, 100 small objects needs more information (memory) than one big.
The rules about how much memory is consumed depend on the JVM implementation and the CPU architecture (32 bit versus 64 bit for example).
For the detailed rules for the SUN JVM check my old blog
Regards, Markus
참고URL : https://stackoverflow.com/questions/258120/what-is-the-memory-consumption-of-an-object-in-java
'Programing' 카테고리의 다른 글
jQuery 템플릿 엔진 (0) | 2020.05.08 |
---|---|
Optional.ofNullable보다 Optional.of를 사용하는 이유는 무엇입니까? (0) | 2020.05.08 |
Symfony 2.x에서 모든 것이 실제로 번들이어야합니까? (0) | 2020.05.07 |
자식 요소에 영향을주지 않고 배경 이미지의 불투명도 설정 (0) | 2020.05.07 |
여러 자식 리포지토리 결합 (0) | 2020.05.07 |