2013-03-19 2 views
8

Java에서 객체의 메모리 풋 프린트가 무엇인지 이해하려고합니다. 나는 this과 자바의 객체와 메모리에 관한 다른 문서들을 읽었다.자바 객체 메모리 풋 프린트 - Visualvm 및 java.sizeOf 측정

그러나 sizeof Java library 또는 visualvm을 사용할 때 나는 이전 참조 (http://www.javamex.com)에 따라 기대할 수있는 것이 전혀없는 두 가지 결과를 얻습니다.

제 테스트를 위해 64-bits Mac에서 Java SE 7 Developer Previewjava.sizeof 0.2.1visualvm 1.3.5으로 사용하고 있습니다.

나는 세 가지 클래스, TestObject, TestObject2, TestObject3이 있습니다.

public class TestObject 
{ 

} 

public class TestObject2 extends TestObject 
{ 
    int a = 3; 
} 

public class TestObject3 extends TestObject2 
{ 
    int b = 4; 
    int c = 5; 
} 

내 주요 클래스 : java.SizeOf와

public class memoryTester 
{ 
    public static void main(String[] args) throws Throwable 
    { 
     TestObject object1 = new TestObject(); 
     TestObject2 object2 = new TestObject2(); 
     TestObject3 object3 = new TestObject3(); 

     int sum = object2.a + object3.b + object3.c; 
     System.out.println(sum); 

     SizeOf.turnOnDebug(); 

     System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(object1))); 
     System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(object2))); 
     System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(object3))); 
    } 
} 

() 내가 얻을 : VisualVM과 함께

{ test.TestObject 
} size = 16.0b 
16.0b 

{ test.TestObject2 
a = 3 
} size = 16.0b 
16.0b 

{ test.TestObject3 
b = 4 
c = 5 
} size = 24.0b 
24.0b 

내가 가진 :

this (Java frame) TestObject #1 16 
this (Java frame) TestObject2 #1 20 
this (Java frame) TestObject3 #1 28 

문서화에 따르면 I 인터넷을 통해 읽으십시오, 저는 64 비트이기 때문에 16 바이트의 객체 헤더를 가지고 있습니다. 확인은 TestObject입니다.

TestObject2에 대해 정수 필드에 4 바이트를 더해야합니다. 다시 채우기의 4 바이트를 더해야합니다. TestObject2에 대해 24 바이트의 총 크기를 제공해야합니다. 내가 잘못?

계속해서 TestObject3에 대해 32 바이트를 제공해야하는 2 개의 정수 필드에 대해 8 바이트 더 추가해야합니다.

VisualVm은 패딩을 무시한 반면 java.sizeOf는 개체 헤더에 포함 된 것처럼 4 바이트를 놓친 것처럼 보입니다. 나는 동일한 결과를주는 4 개의 불린으로 정수를 대체 할 수있다.

질문 :

이유는이 두 가지 도구는 서로 다른 결과를?

패딩이 있어야합니까?

나는 또한 어딘가에 (나는 링크를 찾지 못했다) 클래스와 서브 클래스 사이에 패딩이있을 수 있다는 것을 읽었다. 맞습니까? 이 경우 클래스의 상속 된 트리에 메모리 오버 헤드가 발생할 수 있습니다.

마지막으로, Java가 수행하는 작업에 대해 자세히 설명한 Java 스펙/doc이 있습니까?

도움 주셔서 감사합니다.

업데이트 :

, 나는 부분은 내가 다음 후 열 "크기"를 체크 한 후 "클래스"에서는, 힙 덤프를 만들 VisualVM과의 개체의 크기를 얻기 위해, utapyngo의 의견에 답변을 열 "인스턴스". 오브젝트의 종류마다 1의 경우의 인스턴스 수.

나다니엘 포드 (Nathaniel Ford)의 의견에 대답하기 위해 각 fieds를 초기화 한 다음 내 메인 방법으로 간단한 파이를 사용했습니다. 결과는 바뀌지 않았습니다.

+0

우리는 메모리 소비를 측정하는 방법에 대한 논리를 보지 않고 어느 것이 옳은지 알 길이 없습니다. –

+0

필자의 경우 64 비트 Java 1.7.0-b147의 jvisualvm 1.7.0 (빌드 110325)은 16, 16 및 24를 제공합니다. visualvm으로 측정 할 때 어떤 방법을 사용합니까? – utapyngo

+0

'a', b' 및'c' 회원 필드에 값을 지정하지 않으면 정확한 결과를 얻지 못할 수 있습니다. JVM의 기본 구현에서는 사용되지 않는 필드에 실제로 메모리를 할당 할 필요가 없으며 해당 필드에 대한 포인터를 보유 할 메모리 만 할당합니다. –

답변

2

예 패딩이 발생할 수 있습니다. 스택의 객체가 완전히 최적화되도록하는 것도 가능합니다. JVM만이 특정 시점의 정확한 크기를 알고 있습니다. Java 언어 내에서 크기를 근사화하는 기술은 모두 일치하지 않는 경향이 있기 때문에 JVM에 첨부 된 도구가 가장 정확한 경향이 있습니다. ,

  1. 직렬화 객체와 그 바이트 의 길이를 반환 (잘못된 분명하지만, 상대 비교에 유용)
  2. 목록 항목 반사 : 나는 알고있다 자바 내에서 SIZEOF을 구현하는 세 가지 주요 기술은 및 개체에서 발견 된 각 필드의 하드 코딩 된 크기 상수. 을 좀 정확하도록 튜닝 할 수 있지만 JVM에서의 변경 및 패딩 에서 JVM이 수행 중이거나 수행하지 않을 수도 있습니다.
  3. 목록 항목로드 객체의 , 실행 GC를 작성하고 JVM 힙 크기의 변화 이러한 기술의

없음 정확하지를 비교합니다.

Oracle JVM에서 실행중인 경우 v1.5 이상. 그런 다음 Java 런타임에서 사용하는 C 구조 밖으로 객체의 크기를 직접 읽는 방법이 있습니다. 프로덕션을위한 좋은 아이디어는 아니며 잘못 이해하면 JVM이 손상 될 수 있습니다. 그러나 여기에 블로그 게시물을 올려 놓으시면 흥미로울 수 있습니다. http://highlyscalable.wordpress.com/2012/02/02/direct-memory-access-in-java/

실제로 JVM이하는 일에 대한 문서는 JVM 특정 버전 특정 및 잠재적으로 구성에 따라 다릅니다. 각 구현은 객체를 다르게 처리 할 수 ​​있습니다. 객체를 완전히 최적화하는 정도까지도, 예를 들어 스택에서 전달되지 않은 객체는 힙에 할당되지 않아도됩니다. 일부 JVM은 심지어 객체를 CPU 레지스터 내에 완전히 관리 할 수도 있습니다. 여기서 귀하의 경우는 아니지만 Java 객체의 실제 크기를 얻는 것이 왜 까다로운 지에 대한 예제로 포함합니다.

소금을 꼬집어서 측정 할 때 sizeOf 값을 취하는 것이 가장 좋으며 '측정 기준'으로 만 사용하십시오.

+0

나는 인스트루먼트 패키지와 getObjectSize() 메소드를 사용하여 오브젝트의 크기를 측정하기위한 포인트를 하나 더 추가 할 것이다. java 문서에 기록 된대로 객체의 예상 크기 만 반환합니다. 하지만 JVM에 첨부 된 도구가 가장 정확한 경향이 있다는 말로 당신이 말하고자하는 바입니다. 나는 java.sizeof 라이브러리가 무엇을하고 있는지를 확인했고 getObjectSize() 메소드를 올바르게 사용하고있는 것으로 보인다.나는 visualvm이 똑같이 할 것을 기대한다. 따라서 두 도구 모두 자바 도구를 사용하는 경우 질문이 남아 있습니다. 왜 다른 결과가 나타 납니까? 나는 visulvm 팀에 우편물을 보낼 필요가 있다고 생각합니다. –

관련 문제