머리말
이 기사는 주로 Java의 안전하지 않은 클래스에 대한 관련 내용을 소개합니다. 참조와 학습을 위해 공유됩니다. 나는 아래에서 많이 말하지 않을 것입니다. 자세한 소개를 함께 살펴 보겠습니다.
1. 안전하지 않은 수업 소개
안전하지 않은 클래스는 Sun.Misc 패키지 아래에 있으며 Java 표준에 속하지 않습니다. 그러나 널리 사용되는 고성능 개발 라이브러리를 포함한 많은 Java Basic 클래스 라이브러리는 Netty, Hadoop, Kafka 등과 같은 안전하지 않은 클래스를 기반으로 개발되었습니다.
안전하지 않은 것은 시스템 메모리 리소스에 직접 액세스하고 독립적으로 관리하는 데 사용될 수 있습니다. 안전하지 않은 클래스는 Java 운영 효율성을 향상시키고 Java 언어의 기본 운영 기능을 향상시키는 데 큰 역할을합니다.
안전하지 않은 것은 Java에 남은 백도어로 간주 될 수 있으며 직접 메모리 액세스, 스레드 일정 등과 같은 일부 저수준 작업을 제공합니다.
안전하지 않은 것이 권장되지 않습니다.
안전하지 않은 사용의 예는 다음과 같습니다.
1.1 개인 수업을 인스턴스화하십시오
import java.lang.reflect.field; import sun.misc.unsafe; 공개 클래스 불안한 플레이어 {public static void main (string [] args)은 예외를 던졌습니다 {// Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate Instantiate 불안정. f.setAccessible (true); 안전하지 않은 안전하지 않은 = (안전하지 않은) f.get (null); // 인스턴트 플레이어 플레이어 플레이어 = (플레이어) 불안한.allocateInstance (player.class); player.setName ( "Li Lei"); System.out.println (player.getName ()); }} 클래스 플레이어 {개인 문자열 이름; private player () {} public String getName () {return name; } public void setName (문자열 이름) {this.name = 이름; }} 1.2CAS 작동, 메모리 오프셋 주소 수정을 통해 미터 값을 변경
CAS를 사용하여 Java Concurrency 패키지의 Synchronousqueue에서 Transferstack의 스택 상단을 업데이트하십시오.
/ 안전하지 않은 역학 - 정적 최종 sun.misc.unsafe 안전하지 않음; 개인 정적 최종 긴 헤드 오프셋; static {try {unsafe = sun.misc.unsafe.getunsafe (); 클래스 <?> k = transferstack.class; 헤드 오프셋 = unsafe.objectfieldoffset (k.getDeclaredfield ( "Head")); } catch (예외 e) {새로운 오류 (e) 던지기; }} // 휘발성 스노 드 헤드; // 스택 부울 캐시 드 (snode h, snode nh) {return h == head && unsafe.compareandswapoBject (this, 헤드 오프셋, h, nh);}의 업데이트 {return h == head &&}; 1.3 직접 메모리 액세스
안전하지 않은 직접 메모리 액세스 : 안전하지 않은 상태에서 열린 메모리 공간은 힙 공간을 차지하지 않으며 물론 자동 메모리 복구 기능이 없습니다. C처럼 자유롭게 시스템 메모리 리소스를 사용할 수 있도록하십시오.
2. 안전하지 않은 클래스 소스 코드 분석
안전하지 않은 API의 대부분은 주로 다음 범주를 포함하는 기본 방법입니다.
1) 수업 관련. 주로 클래스 및 정적 필드 작업 방법을 제공합니다.
2) 객체 관련. 주로 물체 및 해당 필드의 작동 방법을 제공합니다.
3) Arrray 관련. 주로 배열 및 요소의 작동 방법을 제공합니다.
4) 동시 상관 관계. 주로 CAS, 스레드 스케줄링, 휘발성, 메모리 배리어 등과 같은 저수준 동기화 프리미티브를 제공합니다.
5) 메모리 관련. 직접 메모리 액세스 방법 (Java 힙을 우회하고 로컬 메모리를 직접 조작하는)을 제공하여 C와 같은 시스템 메모리 자원을 자유롭게 활용할 수 있습니다.
6) 시스템 관련. 주로 주소 크기 및 메모리 페이지 크기와 같은 일부 낮은 수준의 메모리 정보를 반환합니다.
2.1 클래스 관련
// 정적 속성의 오프셋은 해당 클래스 객체에서 정적 속성을 읽고 쓰는 데 사용됩니다. Public Native long staticfieldoffset (필드 F); 공개 기본 대상 정적 필드베이스 (필드 F); // 클래스가 초기화되어야하는지 여부를 판단합니다. 클래스 로더 로더, ProtectionDomain ProtectionAmain); // 클래스를 동적으로 생성하는 데 사용할 수있는 익명 클래스를 정의합니다.
2.2object 관련
기본 유형 (부울, 바이트, 숯, 짧은, int, long, float, double) 및 객체 참조 유형에 대한 다음과 같은 방법이 있습니다.
// 객체의 필드 오프셋을 가져옵니다. 공개 기본 Long ObjectFieldOffset (필드 F); // 주어진 객체 주소의 int 값을 가져옵니다. 오프셋 공개 기본 int getInt (Object O, Long Offset); // 주어진 객체 주소의 int 값을 설정합니다. 오프셋 public void putint (Object O, Long Offset, int x);
// 객체를 생성하지만 생성자는 호출되지 않습니다. 수업이 초기화되지 않으면 클래스가 초기화됩니다. 대중의 원시 대상을 할당 (class <?> cls)은 인스턴티션 지출을 던진다.
2.3 배열 관련
/** * 주어진 배열 클래스의 스토리지 할당에서 첫 번째 요소의 오프셋을보고합니다. {@link #ArrayIndexScale}이 동일한 클래스에 대해 0이 아닌 값 *을 반환하는 경우 해당 스케일 팩터를 사용 하여이 * 기본 오프셋과 함께 주어진 클래스의 배열 요소에 액세스하기 위해 새 오프셋을 형성 할 수 있습니다. * * @see #getint (Object, Long, Int) * /// 배열에서 첫 번째 요소의 오프셋 주소를 반환 공개 기본 int arraybaseoffset (class <?> arrayclass); // boolean, byte, short, int, float, double, double 및 객체 유형은 다음 방법을 가지고 있습니다./ * {@code arraybaseOffset (bolean [])의 값은 다음과 같습니다. array_boolean_base_offset = theunsafe.arraybaseoffset (boolean []. class); /** * 스토리지에서 요소를 해결하기위한 스케일 요인을보고 * 주어진 배열 클래스의 할당. 그러나 "좁은"유형 *의 배열은 일반적으로 {@link * #getByte (Object, int)}와 같은 액세서와 함께 제대로 작동하지 않으므로 해당 클래스의 스케일 계수는 * 0으로보고됩니다. * * @see #ArrayBaseOffSet * @See #getInt (Object, Long) * @see #putInt (Object, Long, int) * // 배열에서 각 요소가 차지하는 크기를 공개 int arrayindexScale (class <?> arrayclass); // 부울, 바이트, 짧은, char, int, float, double 및 객체 유형은 다음 방법을 가지고 있습니다./** {@code arrayindexscale (boolean []. class)}*/public int array_boolean_index_scale = theunsafe.arrayindexScale (boolean []. class); 메모리 배열의 각 요소의 위치는 ArrayBaseOffset 및 ArrayIndexScale을 통해 위치 할 수 있습니다.
2.4 동시성 관련
2.4.1CAS 관련
CAS : CompareAndswap, 메모리 오프셋 주소 오프셋, 예상 값 예상, 새 값 x. 현재 시간에 변수의 값과 예상 값이 같으면 변수의 값을 x로 업데이트하십시오. 업데이트가 성공하면 true를 반환하십시오. 그렇지 않으면 거짓을 반환하십시오.
// 현재 값이 예상되는 경우 변수 값을 x로 업데이트하십시오. // o : 오프셋 오프셋 : 오프셋 예상 : 예상 값 x : 새로운 값 공개 최종 기본 부울 비교 대원 (오브젝트 O, 긴 오프셋, 객체 예상, 개체 x); 공개 최종 네이티브 부울 CompareAndswapint (Object O, Long Offset, int expect, int x); 공개 최종 기본 부울 비교 대원 (Object O, Long Offset, Long Excent, Long X);
Java 8부터 다음과 같은 방법이 안전하지 않은 경우 제공됩니다.
// 공개 최종 int getAndaddint (개체 O, Long Offset, int Delta) {int v; do {v = getIntVolatile (o, 오프셋); } while (! compareAndswapint (o, 오프셋, v, v + delta)); return v;} 공개 최종 Long GetAndadlong (오브젝트 O, Long Offset, Long Delta) {Long V; do {v = getLongVolatile (o, 오프셋); } while (! compareandswaplong (o, 오프셋, v, v + delta)); return v;} // public final int getAndsetInt (오브젝트 O, 긴 오프셋, int newValue) {int v; do {v = getIntValatile (o, 오프셋); } while (! compareAndswapint (o, 오프셋, v, newValue)); return v;} public final long getandsetlong (오브젝트 O, 긴 오프셋, Long NewValue) {long v; do {v = getLongValatile (o, 오프셋); } while (! compareandswaplong (o, 오프셋, v, newValue)); return v;} public final object getAndSetObject (오브젝트 O, Long Offset, Object NewValue) {Object V; do {v = getObjectValatile (o, 오프셋); } while (! compareAndswapoBject (o, 오프셋, v, newValue)); 반환 v;2.4.2 스레드 스케줄링 관련
// 블로킹 스레드 공개 기본 void unpark (객체 스레드); // 블로킹 스레드 공개 네이티브 void Park (부울 isabsolute, 오랜 시간); // 객체 잠금 공개 void moniterenter (Object O); // 공개 void monitorexit (Object O); // 객체 잠금을 얻으려고 시도하는지 여부를 나타내려고 객체 O);
2.4.3 휘발성 관련 읽기 및 쓰기
기본 유형 (부울, 바이트, 숯, 짧은, int, long, float, double) 및 객체 참조 유형에 대한 다음과 같은 방법이 있습니다.
// 객체의 지정된 오프셋에서 변수를 참조하고 휘발성의로드 의미를 사용하십시오. // getObject (개체, 긴) 휘발성 버전과 동등한 getObject (객체, 긴) 공개 기본 개체 getObjectVolatile (Object O, Long Offset); // 변수의 기준을 객체의 지정된 오프셋에 저장하고 휘발성의 스토리지 의미를 사용하십시오. // putobject (Object, Long, Object) public Native void putobjectvolatile (Object O, Long Offset, Object X)의 휘발성 버전에 해당합니다.
/** * {@link #putoBjectVolatile (Object, Long, Object)}의 버전은 상점의 다른 스레드에 대한 즉각적인 가시성을 보장하지 않습니다. 이 방법은 일반적으로 * 기본 필드가 Java 휘발성 (또는 배열 셀 인 경우 휘발성 액세스를 사용하여 만 액세스하는 경우) 인 경우에만 유용합니다. */public Native void potorderedObject (Object O, Long Offset, Object X); /** {@Link #putIntVolatile (Object, Long, Int)}의 ordered/Lazy 버전*/public aviL void potOrderEdint (Object O, Long Offset, int x); /** {@link #putlongvolatile (Object, Long, Long)}의 ordered/Lazy 버전*/public native void potorderedLong (Object O, Long Offset, Long X);2.4.4 메모리 배리어 관련
Java 8은 코드 재정렬을 피하기 위해 메모리 장벽을 정의하기 위해 도입되었습니다.
// 메모리 배리어는로드 작업이 재정렬되는 것을 금지합니다. 로드 및 저장 작업은 Barrier Public Native void Fullfence ()의 전면으로 재정렬되지 않습니다.
2.5 직접 메모리 액세스 (비 eap 메모리)
Allocatememory에 의해 할당 된 메모리는 수동으로 자유롭게되어야합니다 (GC에 의해 재활용되지 않음).
// (부울, 바이트, 숯, 짧은, int, long, float, double) 다음 두 가지 방법이 있습니다. // 주어진 주소에서 int 값을 가져옵니다 공개 기본 int getInt (긴 주소); // 주어진 주소에서 int 값을 설정합니다. 공개 주소, int x); // 로컬 포인터 공개 기본 Long getAddress (긴 주소); // 주어진 메모리 주소에 국소 포인터를 저장하십시오. // 메모리 할당 Public Native Long Allocatememory (긴 바이트); // 메모리를 공개 기본 Long Reallocatememory (긴 주소, 긴 바이트); // 메모리 콘텐츠 초기화 공개 O, 긴 오프셋, 긴 바이트, BYTE 값을 초기화); 주소, 바이트, 값);} // 메모리 콘텐츠 초기화 공개 기본 void copymemory (Object SRCBase, Long SRCOffset, Object DestBase, Long DestOffset, Long Bytes); // 메모리 콘텐츠 초기화 대중 void copymemory (긴 srcaddress, Long Destaddress, Long Bytes) {Null, Srcaddress, null, srcaddress, 널 바이트);} // 릴리스 메모리 공개 네이티브 void 프리 메모리 (긴 주소); 2.6 시스템 관련
// 포인터의 크기를 반환합니다. 반환 값은 4 또는 8입니다. public native int addresssize (); /** {@code addresssize ()}*/public static final int jesdrends _size = theunsafe.addresssize (); // 메모리 페이지의 크기. 공개 기본 int pagesize ();3. 참조 자료
//www.vevb.com/article/140709.htm Java의 안전하지 않은 클래스에 대해 이야기 해 봅시다
//www.vevb.com/article/140721.htm Java Magic Class : Sun.misc.unsafe
요약
위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.