문제

When I'm building a java 오브젝트를 사용하여 CGI 방법을 전달하기 위해,그것은에서 매개 변수는 java 방법은 나를 호출하여 사용하여 CGI invocation API,나는 어떻게 관리하는 메모리가 있습니까?

여기에 무엇이 내가 작업:

나는 C 개체가 소멸하는 방법이 더 복잡는 free().이것 C 개체를 연결할 Java 개체고 나면 응용 프로그램으로 완료 Java 체,나는 더 이상 필요 C 개체입니다.

내가 만드는 Java 개체처럼 너무(오류 검사 elided 명확성을 위해):

c_object = c_object_create ();
class = (*env)->FindClass (env, "my.class.name");
constructor = (*env)->GetMethodID (env, class, "<init>", "(J)V");
instance = (*env)->NewObject (env, class, constructor, (jlong) c_object);

method = (*env)->GetMethodID (env, other_class, "doSomeWork", "(Lmy.class.name)V");
(*env)->CallVoidMethod (env, other_class, method, instance);

그래서,이제는 나를 instance, 어떻게 해야 하나요?상을 남기고 싶 가비지 컬렉션을 VM;을 때 수행 instance 그것은 환상적인 경우에도 불 c_object_destroy() 에서 포인터가 제공됩니다.이것이 가능한가요?

별도 하지만 관련 질문을 함께 할 수 있는 범위 Java 엔터티 내에서 만든 방법은 이와 같은;을 수동으로 해제,말 class, constructor, 나 method 하십니까?JNI doc 은 절망적 모호(에서 내 심판)주제에의 적절한 메모리를 관리합니다.

도움이 되었습니까?

해결책

기본 자원을 되 찾는 몇 가지 전략이 있습니다 (물체, 파일 설명자 등).

  1. 자원을 해제하는 Finalize () 중에 JNI 메소드를 호출하십시오. 어떤 사람들은 최종 구현에 대해 추천합니다, 그리고 기본적으로 당신은 당신의 기본 자원이 결코 해방되었다고 확신 할 수 없습니다. 메모리와 같은 리소스의 경우 이것은 아마도 문제가되지 않을 수 있지만 예를 들어 예측 가능한 시간에 플러시 해야하는 파일이있는 경우, finalize ()가 좋지 않을 것입니다.

  2. 정리 방법을 수동으로 호출합니다. 이것은 자원을 정리해야한다는 것을 알고있는 시점이있는 경우 유용합니다. JNI 코드에서 DLL을 언로드하기 전에 거래 해야하는 리소스가있을 때이 방법을 사용했습니다. DLL이 나중에 다시로드되도록하기 위해 DLL을 내리려고 시도하기 전에 객체가 실제로 처리되었는지 확인해야했습니다. Finalize () 만 사용하면이 보장을받지 못했을 것입니다. 이는 (1)과 결합하여 최종화 () 또는 수동으로 호출 된 청소 방법에서 리소스를 할당 할 수 있습니다. (정리 방법을 호출 해야하는 객체를 추적하려면 약한 references의 정식지도가 필요할 것입니다.)

  3. 아마도 유령 회의 이 문제를 해결하는 데 사용될 수 있지만 그러한 솔루션이 어떻게 작동하는지 정확히 잘 모르겠습니다.

사실, 나는 JNI 문서에서 당신과 동의하지 않아야합니다. 나는 그것을 찾았다 JNI 사양 로컬 및 글로벌 참조 관리에 관한 섹션이 더 정교 해졌지만 대부분의 중요한 문제에 대해 매우 명확합니다.

다른 팁

JNI spec 커버의 문제는 사람"소유"Java 에서 만들어진 개체 JNI 방법 .필요하신 사이 구별 글로벌 참조가 있습니다.

때 JVM 을 만들 JNI 를 호출하는 네이티브 코드를 설정하는 레지스트리의 추적을 유지 모든 개체가 만들어집니다.모든 개체 동안 만들어진 기본 호출(즉에서 반환하는 사용자 인터페이스 기능)의 추가를 이 레지스트리에 있습니다.대한 참조를 이러한 객체로 알려져있다 현지 참조.기본 방법을 반환하는 JVM,모든 로컬 참조 동안 만들어진 기본 메소드 호출이 파괴됩니다.당신이 전화를 만들기로 JVM 동안 native 방법 로컬 참조은 여전히 살아 있을 때 제어의 기본 방법입니다.는 경우 JVM 에서 호출 기본 코드에게 다른 통화로 다시 기본 코드에 새로운 레지스트리의 로컬 참조를 만들과 같은 규정이 적용됩니다.

(사실을 구현할 수 있습니다 당신의 자신의 JVM 실행 파일을(즉java.exe 사용)사용자 인터페이스를 만들어 JVM(함으로써 수신 JNIEnv*)를 포함하고,클래스에 주어진 명령 라인,그리고 호출하는 main()메소드에습니다.)

모든 참조는 반환에서 사용자 인터페이스 방법은 지역.즉,일반적인 상황에서 당신은 필요하지 않을 수동으로 할당을 참조는 반환에 의해 사용 방법,그 이후 그들은 때 파괴를 반환 JVM.때때로 당신은 여전히 그들을 파괴하려는"중간"는 경우,예를 들면,당신의 많은 지역을 참조하려는 삭제로 돌아가기 전에 JVM.

글로벌 참가 만들어(현지에서 참조)사용하여 NewGlobalRef().추가되는 특별한 레지스트리가 할당 취소할 수 있습니다.글로벌 참조용으로만 사용됩 Java 체는 기본 코드를 요구하려는 여러 번 호출하는 경우,예를 들어,당신은 기본 코드 이벤트를 트리거하는 전파될 Java.이 경우에는 사용자 코드를 저장해야에 대한 참조 자바 객체을 받는 이벤트입니다.

이 명확히 희망의 메모리 관리 문제는 약간의 비트입니다.

Re : "별도의 관련 질문"... "로컬"컨텍스트에서 사용할 때 JCLASS, JFIELDID 및 JMETHODID를 수동으로 릴리스 할 필요는 없습니다. 당신이 얻은 실제 객체 참조 (JCLASS, JFIELDID, JMETHODID)는 deletelocalref와 함께 해제해야합니다.

GC는 인스턴스를 수집하지만 기본 코드에 할당 된 비 자바 힙 메모리를 자동으로 해제하지는 않습니다. C_Object 인스턴스를 해제하려면 클래스에 명시적인 방법이 있어야합니다.

이것은 C_Object가 출시되어 해제 된 경우 최종화기 확인을 권장하는 경우 중 하나입니다. 그렇지 않은 경우 메시지를 기록합니다.

유용한 기술은 Java 클래스 생성자에서 던질 수있는 인스턴스를 만들어 필드에 저장하는 것입니다 (또는 필드 인라인을 초기화). Finalizer가 클래스가 제대로 배치되지 않았 음을 감지하면 스택 트레이스를 인쇄하여 할당 스택을 정확히 찾아냅니다.

제안은 똑바로 JNI를 피하고 함께가는 것입니다. 접착제 또는 통음 (둘 다 코드를 생성하고 정적으로 연결될 수 있습니다).

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