JNI 전역 참조 및 JFrame.dispose()방법

문제 설명
jProfiler 로 자바 swing 프로그램의 메모리 누 출 문 제 를 분석 할 때 메모리 에 있 는 JFrame 인 스 턴 스 의 수량 이 계속 증가 하고 있 는 것 을 발견 했다.
각 frame 이 열 리 고 닫 힙 니 다(closed).
jProfiler 를 통 해 GC Root 를 볼 때'JNI Global reference'하나만 찾 을 수 있 습 니 다.
이것 은 무슨 뜻 입 니까?왜 그 는 모든 frame 인 스 턴 스 를 걸 었 습 니까?
대답
위 키 피 디 아 에서 자바 로 컬 인터페이스 에 대한 소 개 를 보십시오.본질 적 으로 자바 프로그램 과 시스템 라 이브 러 리 간 의 통신 을 허용 합 니 다.
JNI 전역 인용 은 메모리 누 출 을 초래 하기 쉽 습 니 다.자동 쓰레기 수집 에 의 해 정리 되 지 않 기 때문에 프로그래머 가 명시 적 으로 풀 어야 합 니 다.JNI 코드 를 만 들 지 않 았 다 면 사용 하 는 라 이브 러 리 에 메모리 누 출 이 있 었 을 수도 있 습 니 다.
수정:local vs.global references 에 대한 더 많은 정 보 를 참고 하 십시오.전역 인용(및 방출 방법)을 사용 하 는 이 유 를 소개 합 니 다.
대답
JNI 전역 참조(JNI global reference)는"native"코드 가 메모리 에 있 는 자바 대상 을 가리 키 는 참조 입 니 다.쓰레기 수집 기 를 막 는 것 이 목적 입 니 다.native 코드 에 사용 되 고 있 는 대상 을 잘못 회수 하지 마 십시오.만약 자바 대상 이 자바 코드 가 없 으 면 사용 합 니 다.
JFrame 인 스 턴 스 는 창java.awt.Window이 고 로 컬Window대상 과 연 결 됩 니 다.특정 JFrame 인 스 턴 스 의 작업 이 끝났다 면dispose()방법 으로 청 소 를 해 야 합 니 다.
로 컬 코드 가 JFrame 을 가리 키 는 전역 인용 을 만 들 었 는 지 는 확실 하지 않 지만 맞 을 것 입 니 다.전역 인용 을 만 들 었 다 면 JFrame 대상 이 GC 에 회수 되 는 것 을 막 을 수 있 습 니 다.프로그램 에 많은 Window 대상(또는 하위 대상)을 만 들 었 고 dispose()를 호출 하지 않 았 다 면 GC 에 의 해 영원히 회수 되 지 않 았 을 것 입 니 다.이 는 스텔스 메모리 유출 을 초래 합 니 다.
부분 참조 및 전역 참조 안내
JNI 는 native 방법 에 전 달 된 모든 대상 형 매개 변수 에 인용 을 만 들 었 으 며 JNI 함수 에서 돌아 온 모든 대상 에 인용 을 만 들 었 습 니 다.
이 인용 들 은 자바 대상 이 GC 에 의 해 정리 되 는 것 을 막 을 것 이다.자바 대상 이 최종 적 으로 풀 려 날 수 있 도록 JNI 는 기본적으로 부분 참조(local references)를 만 들 었 습 니 다.이 컴퓨터 방법 이 되 돌아 오 면 만 든 부분 참조 가 실 효 됩 니 다.물론 네 이 티 브 방법 은 부분 적 인 인용 을 다른 곳 에 저장 하고 후속 호출 에서 재 활용 하려 고 해 서 는 안 된다.
예 를 들 어 다음 프로그램FieldAccess.c의 변종 native 방법)에서 자바 류 의 ID field 를 잘못 캐 시 했 습 니 다.매번 필드 이름과 서명 을 통 해 ID field 를 검색 하지 않 아 도 됩 니 다.
/* !!!          */
static jclass cls = 0;
static jfieldID fid;

JNIEXPORT void JNICALL
Java_FieldAccess_accessFields(JNIEnv *env, jobject obj)
{
  ...
  if (cls == 0) {
    cls = (*env)->GetObjectClass(env, obj);
    if (cls == 0)
      ... /* error */
    fid = (*env)->GetStaticFieldID(env, cls, "si", "I");
  }
  ... /* access the field using cls and fid */
}

이 프로그램 은 잘못된 것 입 니 다.GetObjectClass에서 돌아 오 는 부분 인용 은 native 방법 으로 돌아 가기 전에 만 유효 하기 때 문 입 니 다.두 번 째 진입Java_FieldAccess_accessField방법 은 잘못된 local reference 를 참조 합 니 다.이 는 잘못된 결 과 를 초래 하고 JVM 붕 괴 를 초래 할 수 있다.
이 문 제 를 해결 하려 면 전역 참조(global reference)를 만 들 수 있 습 니 다.전체 인용 은 명시 적 으로 풀 릴 때 까지 유효 합 니 다.
/*      OK  */
static jclass cls = 0;
static jfieldID fid;

JNIEXPORT void JNICALL
Java_FieldAccess_accessFields(JNIEnv *env, jobject obj)
{
  ...
  if (cls == 0) {
    jclass cls1 = (*env)->GetObjectClass(env, obj);
    if (cls1 == 0)
      ... /* error */
    cls = (*env)->NewGlobalRef(env, cls1);
    if (cls == 0)
      ... /* error */      
    fid = (*env)->GetStaticFieldID(env, cls, "si", "I");
  }
  ... /* access the field using cls and fid */
}

자바 클래스 가 마 운 트 해제 될 때 까지 전역 참조 가 존재 합 니 다.따라서 다음 에 자바 류 의 ID 필드 를 사용 할 때 항상 유효 하 다 는 것 을 보증 합 니 다.native 코드 가 전역 인용 을 사용 하지 않 을 때DeleteGlobalRefs함 수 를 호출 해 야 합 니 다.그렇지 않 으 면,대응 하 는 자바 대상(예 를 들 어 cls 가 인용 한 자바 클래스)은 영원히 마 운 트 해제 되 지 않 습 니 다.
대부분의 경우 네 이 티 브 프로 그 래머 는 VM 에 의 해 모든 부분 인용 을 방출 해 야 합 니 다.어떤 특수 한 상황 에서 네 이 티 브 코드 도DeleteLocalRef함 수 를 호출 하여 부분 인용 을 명시 적 으로 삭제 할 수 있 습 니 다.이러한 상황 은 다음 과 같다.
거대 한 자바 대상 을 인용 하여 현재 네 이 티 브 방법 이 되 돌아 올 때 까지 기다 리 지 않 고 자바 대상 을 GC 에서 회수 합 니 다.예 를 들 어 다음 프로그램 에서 GC 는lref인 용 된 자바 대상 을 방출 할 수 있 으 며,이때 lengthy Computation 방법 은 실행 중 입 니 다.
  lref = ...            /* a large Java object */
  ...                   /* last use of lref */
  (*env)->DeleteLocalRef(env, lref);

  lengthyComputation(); /* may take some time */

  return;               /* all local refs will now be freed */
}

native 방법 에서 대량의 부분 인용 을 만 들 수도 있 습 니 다.JNI local reference table 이 넘 칠 수 있 습 니 다.이 럴 때 사용 하지 않 는 부분 인용 을 삭제 하 는 것 이 필요 합 니 다.예 를 들 어 다음 프로그램 에서 native 코드 는 자바 문자열 로 구 성 된 큰 배열 을 옮 겨 다 닙 니 다.교체 할 때마다 문자열 요소 의 부분 적 인 인용 을 방출 할 수 있 습 니 다.
  for(i = 0; i < len; i++) {
    jstring jstr = (*env)->GetObjectArrayElement(env, arr, i);
    ...                                /* processes jstr */ 
    (*env)->DeleteLocalRef(env, jstr); /* no longer needs jstr */
  }

참고:
  • stackoverflow: What is ‘JNI Global reference’
  • Local and Global References

  • 닻http://blog.csdn.net/renfufei
    년 01 월 28 일

    좋은 웹페이지 즐겨찾기