2017-10-13 2 views
2

를 호출?JMM 보증은 다음 코드 샘플을 감안할 때

과 같은 구현 세부 정보는 의도적으로 제외됩니다. method1은 closable을 캡처합니까?이 질문의 첫 번째 부분에 나와 있습니다.

static char* value; 

void capture(char* ptr){ 
     value = ptr; 
} 

int len(void) { 
    return strlen(value); 
} 

이 네이티브 라이브러리가

interface CApi extends Library { 

static { 
    Native.register("test.so", CApi.class) 
} 

    void capture(Pointer s); 
    int test(); 
} 

JNA

를 사용하여 포장한다 : 내가 같이 요약 될 수있는 C 라이브러리가

:


내 spefic 사용 사례는 이것이다 그리고 내 원래 클라이언트 코드는 다음과 같습니다.

cApi = Native.loadLibrary("test.so", CApi.class); 


byte[] data = Native.toByteArray("foo"); 
Memory m = new Memory(data.length + 1); 
m.write(0, data, 0, data.length); 
m.setByte(data.length, (byte)0); 

cApi.capture(m); 
System.out.print(cApi.len()); 

이 첫 번째 버전의 문제는 m이 Java에서 할당되었으며이 메모리의 수명주기가 매우 가까워서 m에 연결되어 있다는 것입니다. 에서 GC의 차기

내가 JNA의 MemoryAutoClosableMemory을 소개하는 서브 클래스 제안이를 방지하기 위해 (JNA는 기본 메모리를 확보 할 수 finalize에 의존) 때 capture(m) 메모리가 해제됩니다 일단 m는 더 이상 강력하게 도달 할 수 없습니다. 아이디어는 리소스를 사용하는 try를 사용하면 자원이이 범위 내에서 강하게 도달 할 수 있음을 분명하게 나타냅니다. 우리가 네이티브 메모리를 해제 할 수 있다는 보너스는 곧 GC를 기다릴 필요없이 더 이상 필요하지 않게되었습니다 (이봐, RAII입니다!).

try (AutoClosableMemory m = [...]) { 
    cApi.capture(m); 
    cApi.test(); 
} 

오전 나는 m.close()cApi.test()m 강력하게 연결할 수 있는지 호출되지 않습니다 보장? 이 경우 m은 기본 C API에 의해 캡처되지만 Java 컴파일러는이를 알 수 없습니다.

답변

4

이론적으로 JVM은 명령어를 재정렬 할 수 있지만 메소드의 결과는 정확해야합니다. HotSpot은 네이티브 코드를 이해하지 못하고 정확성을 보장하기 위해 네이티브 명령어 주위의 코드를 재 순서화하지 ​​않습니다.

+0

'네이티브 명령어 주위에 코드를 재정렬하지 않는다'와 같은 것을 찾고있었습니다. 그 링크가 있습니까? – Oleg

+1

네이티브 코드 블록은 JLS에서 외부 작업으로 공식화됩니다. 그들은 이전 코드와 후속 코드와의 관계 이전에 일어난 일을 암시합니다. 나는이 프리젠 테이션을 통해 도움이 될만한 정보를 얻었습니다. https://youtu.be/XgiXKPEILoc 40 분에 외부 행동에 대해 이야기합니다. –

+1

감사합니다. 나는 당신이 당신의 대답에 그것을 덧붙여 야한다고 생각합니다. [여기] (https://youtu.be/XgiXKPEILoc?t=40m37s)에서 OP의 질문에 대해 자세히 설명합니다. – Oleg

1

한 스레드의 경우 모든 것이 코드에서와 동일한 순서로 정확히 실행됩니다 (어떤 순서 변경도 프로그램에 아무런 영향을 미치지 않습니다). 재정렬은 다른 스레드가 어떤 일이 발생 하는지를 보는 방법에만 영향을줍니다. 귀하의 질문에 하나의 스레드가 있으므로 전에 cApi.test()을 호출하도록 프로그램이 보장됩니다.

+0

그건 내 이해입니다. 그러나, 특히 컴파일러가 닫는 순서를 바꾸는 것을 막는 것을 이해하고 싶습니다. Java의 관점에서 볼 때, 두 문 사이에 의존 관계가 없으므로 닫기를 이동하면 _as-if-serial_이 중단되지 않습니다. –

+0

@ ClémentMATHIEU 글쎄, 만약 당신의 프로그램에 영향을 미친다면 시리얼처럼 깨질 것이다. 더 구체적인 것을 찾으려고 노력하지만 일반적으로 항상 사실입니다. 이것은 자바의 관점이 아니라 JVM과 CPU가 무엇을 얻을 수 있는지를 안다. – Oleg