문제

이 질문은 특히 Java 언어를위한 것입니다. 나는 모든 정적 코드에 대한 정적 메모리 보호가 따로 설정되어 있음을 이해합니다.

내 질문은이 정적 메모리가 어떻게 채워져 있습니까? 정적 객체가 가져 오기에 정적 메모리에 넣습니까? 또한 다른 모든 개체와 마찬가지로 정적 객체에 동일한 쓰레기 수집 규칙이 적용됩니까?


public class Example{
    public static SomeObject someO = new SomeObject();
}
/********************************/
// Is the static object put into static memory at this point?
import somepackage.Example;

public class MainApp{
    public static void main( Sting args[] ){
// Or is the static object put into memory at first reference?
       Example.someO.someMethod();
// Do the same garbage collection rules apply to a 
//     static object as they do all others?
       Example.someO = null;
       System.gc();
    }
}
도움이 되었습니까?

해결책

가져 오기는 컴파일 된 코드의 지침과 관련이 없습니다. 컴파일 타임에만 사용하기위한 별칭을 설정합니다.

클래스를로드 할 수는 있지만 아직 초기화되지 않은 몇 가지 반사 방법이 있지만 대부분의 경우 클래스를 참조 할 때마다 초기화되었다고 가정 할 수 있습니다.

정적 멤버 이니셜 라이저 및 정적 블록은 소스 코드 순서에서 하나의 정적 이니셜 라이저 블록 인 것처럼 실행됩니다.

정적 멤버 변수를 통해 참조 된 객체는 클래스가 언로드 될 때까지 강력하게 참조됩니다. 정상 ClassLoader 클래스를 언로드하지 않지만 응용 프로그램 서버에서 사용하는 클래스는 올바른 조건에서 수행됩니다. 그러나 그것은 까다로운 영역이며 진단하기 어려운 메모리 누출의 원천이되었습니다. 즉, 전역 변수를 사용하지 않는 또 다른 이유가 있습니다.


(접선) 보너스로서, 다음은 까다로운 질문입니다.

public class Foo {
  private static Foo instance = new Foo();
  private static final int DELTA = 6;
  private static int BASE = 7;
  private int x;
  private Foo() {
    x = BASE + DELTA;
  }
  public static void main(String... argv) {
    System.out.println(Foo.instance.x);
  }
}

이 코드는 무엇을 인쇄합니까? 시도해 보면 "6"을 인쇄 할 것입니다. 여기에는 몇 가지 작업이 있으며 하나는 정적 초기화 순서입니다. 코드는 다음과 같이 작성된 것처럼 실행됩니다.

public class Foo {
  private static Foo instance;
  private static final int DELTA = 6;
  private static int BASE;
  static {
    instance = null;
    BASE = 0;
    instance = new Foo(); /* BASE is 0 when instance.x is computed. */
    BASE = 7;
  }
  private int x;
  private Foo() {
    x = BASE + 6; /* "6" is inlined, because it's a constant. */
  }
}

다른 팁

일반적으로 "정적"메모리와 같은 것은 없습니다. 대부분의 VM은 영구적 인 힙 생성 (클래스가로드되는 곳)을 가지고 있으며, 이는 일반적으로 수집되지 않습니다.

정적 객체는 다른 객체와 마찬가지로 할당됩니다. 그러나 그들이 오랫동안 살면 쓰레기 수집가의 다른 세대 사이에서 움직일 것입니다. 그러나 그들은 permgenspace에서 끝나지 않을 것입니다.

수업 이이 개체를 영구적으로 보유하는 경우 VM이 종료 될 때만 해제됩니다.

이 정적 변수 일부 수업이 코드에서 참조 되 자마자 초기화됩니다. 예에서 이것은 주요 메소드의 첫 번째 줄에서 실행됩니다.

정적 이니셜 라이저 블록을 만들어이를 검증 할 수 있습니다. 이 이니셜 라이저 블록에 브레이크 포인트를 넣으면 전화가 표시되는 시점이 표시됩니다. 또는 더 단순한 ... someobject의 생성자에 중단 점을 넣으십시오.

정적 변수의 초기화는 섹션에서 다룹니다 2.11 정적 초기화기 SUNS JVM SPEC. 이 사양은 쓰레기 수집의 구현을 정의하지 않지만 정적 객체에 대한 쓰레기 수집 규칙은 VM에 따라 다를 것이라고 생각합니다.

포인터 (또는 다른 원시 유형)만이 페름기 공간 (정적 물건이 저장되는 영역의 적절한 이름입니다).

따라서 포인터로 언급 된 물체는 다른 물체와 마찬가지로 일반 힙에 앉습니다.

정적 필드가 다른 객체를 참조하도록 변경되면, 정적 필드가 가리키는 원래 물체는 다른 객체와 마찬가지로 GC에 적합합니다.

클래스 자체가 언로드되고 전체 객체 그래프가 힙에서 잘린 경우 (무효가되지 않더라도) 무료로 사용할 수도 있습니다. 물론 수업을 내릴 수있는 경우 다른 많은 질문에 좋은 주제입니다 ... :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top