나는 sun.misc.Unsafe의 문서를 이해하는 데 어려움을 겪고있다. 일반적인 용도로 사용되지는 않았으므로 누구도 읽을 수 없도록 만들지는 않았지만 실제로는 배열의 요소 (그래서 포인터를 네이티브 코드에 전달할 수 있음). 누구든지이 작업을 수행하는 코드가 있습니까? 믿을만한가요?sun.misc.Unsafe를 사용하여 Java 배열 항목의 주소를 가져 오시겠습니까?
답변
배열을 사용하는 대신 ByteBuffer.allocateDirect() 직접 버퍼를 사용할 수 있습니다. 이것은 필드에 주소를 가지며이 주소는 ByteBuffer의 수명 동안 변경되지 않습니다. 직접 ByteBuffer는 최소의 힙 공간을 사용합니다. 리플렉션을 사용하여 주소를 가져올 수 있습니다.
Unsafe를 사용하여 주소를 가져올 수 있지만 문제는 GC가 언제든지 이동할 수 있다는 것입니다. 객체는 메모리에 고정되어 있지 않습니다.
JNI에서는 특수한 방법을 사용하여 Java 객체간에 데이터를 복사하여이 문제 (및 기타 문제)를 피할 수 있습니다. C 코드로 객체간에 데이터를 교환하려면 이러한 메소드를 사용하는 것이 좋습니다.
바이트 배열이라는 용어로 정의 된 기존 API를 구현하려고 할 때 직접 바이트 버퍼 (문제를 쉽게 해결할 수 있음)를 사용하지 않으려 고하고 복사의 페널티를 피하려고합니다. 여분의 버퍼 세트로부터. 이것은 최후의 수단으로 충분하지만 더 나은 방법이 있어야합니다. JNI를 사용하면 더 쉽게 작업 할 수 있지만 불행히도 전체 배열 작업 이외의 작업을 수행하는 데 필요한 인터페이스가없는 JNA와 함께 작업하고 있습니다. – Jules
@Jules, JNI는 GC를 손상시킬 수있는'GetPrimitiveArrayCritical '이있는 경우를 제외하고는 자체적으로 복사본을 생성합니다. 글 머리 기호를 물고 직접 (버퍼) 메모리로 복사하십시오. 그게 유일한 실현 가능한 해결책입니다. 예를 들어 impl. FileOutputStream (SocketOutputStream extends)은 스택에있는 요소의 복사본을 사용합니다. 가장 높은 비용은 어느 쪽이든 지불해야하는 데이터 (및 캐시 미스, 심지어)의로드 비용과 함께 발생하기 때문에 복사에 대한 처벌은 그다지 높지 않습니다. 복사하면 캐시 라인을 미리 가져 오게되므로 원시 코드의 작동 방식을 더 잘 파악하지 못하는 것일 수 있습니다. – bestsss
@Jules, 사이드 노트 : javax.net.ssl.SSLEngine조차도 버퍼를 사용할 수 있으며, 모든 알고리즘은 byte []이며 직접 버퍼를 임시 배열에 복사하는 결과를 낳습니다. 이것은 역 이야기이며 도덕적입니다. SSLEngine에 의한 직접 버퍼를 사용하지 않는다. – bestsss
다음은 작동하는 샘플입니다. JVM을 부적절하게 사용하여 Unsafe
클래스를 쉽게 크래시 할 수 있으므로주의하십시오.
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class UnsafeTest {
public static void main(String... args) {
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
int ten = 10;
byte size = 1;
long mem = unsafe.allocateMemory(size);
unsafe.putAddress(mem, ten);
long readValue = unsafe.getAddress(mem);
System.out.println("Val: " + readValue);
}
}
그 코드는 DirectByteBuffer가 어떻게 작동하는지 완벽하게 안전해야합니다. 불행히도 기존 배열의 데이터에 액세스하는 것은 내가 원하는 작업을 수행하지 않습니다. – Jules
@StephenC, 코드는 완벽하게 괜찮습니다. 기본적으로'char * mem = malloc (size); ... '은 GC에 의해 결코 건드리지 않으며, 리얼하지 않는 한 네이티브 C 누출을 일으 킵니다. – bestsss
코드는 괜찮지 만 할당 된 메모리를 확보하는 것도 고려해야합니다. DirectByteBuffer를 참조 해주세요. 또한 할당 된 메모리가 0이 아니므로 직접 배열이 0으로 초기화되었다고 가정 할 수 없습니다. –
- 1. . __import__를 사용하여 x를 가져 오시겠습니까?
- 2. 로그인 한 페이스 북 사용자로부터 이메일 주소를 가져 오시겠습니까?
- 3. Java에서 Array의 일부만 가져 오시겠습니까?
- 4. MapXtreme2008을 사용하여 Ascii/Grid 파일을 가져 오시겠습니까?
- 5. BCP를 사용하여 IBM Timestamp를 가져 오시겠습니까?
- 6. Matlab에서 구조체를 사용하여 Excel에서 데이터를 가져 오시겠습니까?
- 7. java를 사용하여 데이터베이스에서 Excel로 데이터를 가져 오시겠습니까?
- 8. Javascript를 사용하여 기본 미디어 플레이어를 가져 오시겠습니까?
- 9. IFrame에서 URL을 가져 오시겠습니까?
- 10. 어떤 라이브러리를 가져 오시겠습니까?
- 11. total_form_count의 ID를 가져 오시겠습니까?
- 12. Android - 텍스트를 가져 오시겠습니까?
- 13. 모델을 앞쪽으로 가져 오시겠습니까?
- 14. 양식 배열 또는 배열 주소를 인쇄하려고하는데 ... 가져 오지 못하나요?
- 15. 런타임 전에 스테이지에 배치 된 기호를 배열 형태로 가져 오시겠습니까?
- 16. 프로세스 상태를 웹으로 가져 오시겠습니까?
- 17. Javascript Associative Array의 슬라이스를 가져 오시겠습니까?
- 18. yahoo ID 또는 yahoo guid를 사용하여 Yahoo 이메일 주소를 가져 오시겠습니까?
- 19. .war 파일에서 내 Java 소스 코드를 가져 오시겠습니까?
- 20. android 프로젝트의/assets 폴더에서 .java 파일을 가져 오시겠습니까?
- 21. 다른 배열 항목의 배열은
- 22. 배열 항목의 GetType()?
- 23. PHP는 배열 항목의 변수가
- 24. 요청 URI에서보기 기능을 가져 오시겠습니까?
- 25. CKEditor 콘텐츠를 가져 오시겠습니까? - jQuery를
- 26. VTK 파일을 웹에 가져 오시겠습니까?
- 27. 실행중인 앱 패키지를 가져 오시겠습니까?
- 28. 다음 코드에서 'href'값을 가져 오시겠습니까?
- 29. Excel/XLS를 SSIS로 가져 오시겠습니까?
- 30. index 대신 document.styleSheets를 가져 오시겠습니까?
http://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafe –
[개발자가 프로그램을 작성해야하는 이유 전화 '태양'패키지] (http://www.oracle.com/) .com/technetwork/java/faq-sun-packages-142232.html) – BalusC
imo, unsafe doc은 꽤 좋지만 어쨌든 일반 대중을위한 것은 아닙니다. 몇 가지 지침이 필요하면 java.util.concurrent와 java.util.concurrent.atomic 읽기 시작하십시오. unsafe는 C (또는 원하는 경우 어셈블러)와 매우 비슷합니다. 만약 경험이 없다면 안전하지 않은 것이 아닙니다. Java 코드를 분해하는 방법 : http://wikis.sun.com/display/HotSpotInternals/PrintAssembly – bestsss