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 */
}
참고:
닻http://blog.csdn.net/renfufei
년 01 월 28 일
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.