이 기사의 본문을 시작하기 전에 다음 코드를 살펴 보겠습니다.
Java에서 정수 클래스의 Integercache의 역할
패키지 이름 : java.lang
파일 이름 : integer.java
메소드 이름 : IntegerCache
이 방법의 코드는 다음과 같습니다.
개인 정적 클래스 integercache {정적 최종 INT High; 정적 최종 정수 캐시 []; 정적 {최종 int low = -128; // 높은 값은 속성 int h = 127로 구성 될 수 있습니다. if (integercachehighpropvalue! = null) {// long.decode 여기에서 초기화하려면 int i = long.decode (integercachehighpropvalue) .intvalue (); i = math.max (i, 127); // 최대 배열 크기는 정수입니다 .max_value h = math.min (i, integer.max_value - low); } High = H; 캐시 = 새 정수 [(High -Low) + 1]; int j = 낮음; for (int k = 0; k <cache.length; k ++) 캐시 [k] = 새 정수 (j ++); } private integercache () {}}코드에서 LOW는 -128이고 높음은 127입니다. 이러한 방식으로 Java 프로그래밍에서 -128-127 간격의 객체를 사용하려면이 캐시의 객체를 직접 사용합니다.
위의 것은 모든 사람들이 IntegerCache를 이해하도록 돕는 간단한 소개입니다. 다음은이 기사의 본문입니다.
소개
5 년 전, 나는 헝가리어에 JDK에서 IntegerCache를 변경하는 방법에 대한 게시물을 게시했습니다. 이 접근법은 실제로 Java 런타임에 깊이 들어가며 실제로 시나리오에서 사용되지 않습니다. 이 연구 코드를 개발할 때 반사의 작동 방식과 정수 클래스가이를 구현하는 방법을 더 잘 이해할 수 있습니다.
정수 클래스에는 integercache라는 개인 중첩이 있는데, 여기에는 -127에서 128 범위의 값을 가진 정수 객체가 포함되어 있습니다.
코드를 int 유형에서 정수 객체로 둘러싸고 값 이이 범위 내에있는 경우 Java 런타임은 새 정수 개체를 만드는 대신이 캐시를 사용합니다. 이것은 주로 성능 최적화 고려 사항을위한 것입니다. 우리는 많은 INT 값이 프로그램 의이 범위 내에 종종 배열의 첨자 색인과 같은 범위 내에 있음을 명심해야합니다.
이것의 부작용은 값이 범위 내에있는 한 동일한 부호 연산자를 사용하여 두 개의 정수 객체를 비교할 때 여러 번 유효하다는 것입니다. 이것은 단위 테스트에서 일반적입니다. 실행 모드에서는 값이 128보다 큰 경우 코드 실행이 실패합니다.
반사를 사용하여 IntegerCache 클래스에 액세스하면 이상한 부작용이 발생할 수 있습니다. 이는 전체 JVM에 영향을 미칩니다. 서블릿이 작은 정수 캐시 값을 재정의하면 동일한 Tomcat에서 실행되는 다른 모든 서블릿도 같은 문제를 겪습니다.
Lukas Eder와 Sitepoint에는 위에 다른 기사가 있습니다.
이제 Java 9의 초기 릴리스를 가지고 놀았으므로 항상 내 마음 속에서해야 할 일은 새로운 Java 버전을 실험하는 것입니다. 시작하기 전에 Java 8에서 수행하는 방법을 살펴 보겠습니다.
Lukas의 기사에서 나는 그의 샘플 코드를 여기에 게시했습니다.
import java.lang.reflect.field; import java.util.random; public class altropy {public static void main (string [] args)은 예외 {// 반사 클래스 <<? > clazz = class.forname ( "java.lang.integer $ integercache"); 필드 필드 = clazz.getDeclaredfield ( "캐시"); field.setAccessible (true); Integer [] cache = (integer []) field.get (Clazz); // (int i = 0; i <cache.length; i ++)에 대한 정수 캐시를 다시 작성합니다. {cache [i] = new Integer (new random (). nextint (cache.length)); } // (int i = 0; i <10; i ++) {System.out.println ((Integer) i); }}}이 코드는 반사를 통해 IntegerCache에 액세스 한 다음 임의의 값을 사용하여 캐시를 채 웁니다 (Naughty!).
우리는 Java 9에서 동일한 코드를 실행하려고 노력합니다. 누군가가 그것을 위반하려고 할 때 Java 9가 더 제한적이라는 것을 알게 될 것입니다.
스레드 예외 "main"java.lang.reflect.inaccessibleObjectException : 필드 정적 최종 최종 Java.lang.integer [] java.lang.integer $ integercache.cache accessible을 만들 수 없습니다 : module java.base는 "Opens java.lang"으로 "named module @1bc6a36e.
이 프로그램은 Java 8에서는 발생하지 않는 예외를 발생시킵니다. 객체는 모델 기반이 아니라고 말하는 것과 같습니다. Java.base 모듈로 인해 JDK의 필수 부분입니다. 각 Java 프로그램이 시작되면 자동으로 가져오고 이름이없는 모듈을 열 수 없습니다. 이 예외는 필드 액세스 가능한 속성을 설정하려고 할 때 발생합니다.
새로운 모듈 시스템이이를 보호하기 때문에 Java 9에서는 Java 8에서 쉽게 액세스 할 수있는 객체는 이제 Java 9에서 액세스 할 수 없습니다. 코드는 클래스가 동일한 모듈에 있거나 모듈에 반사 액세스를 위해 패키지가 열린 경우에만 반사로 액세스 할 수있는 필드, 메소드 및 기타 정보에만 액세스 할 수 있습니다. 이것은 module-info.java module 정의 파일을 통해 구현할 수 있습니다.
MODULE MYMODULE {EXPORTS COM.JAVAX0.MODULE.DEMO; Opens com.javax0.module.demo;} 이 모듈 Java.base는 특히 이름이없는 모듈의 경우 반사 액세스를 위해 자체적으로 열 필요가 없습니다. 모듈을 만들어 이름을 작성하면 오류 메시지에는 모듈 이름이 포함됩니다.
프로그램에서 모듈을 열 수 있습니까? java.lang.reflect.Module 모듈에는 완료 할 수있는 추가 펜스 방법이 있습니다.
가능합니까?
개발자에게 나쁜 소식은 다음과 같습니다. 가능하지 않습니다. 다른 모듈의 모듈에서만 패키지를 열 수 있으며이 메소드를 호출하여 해당 모듈에서 패키지가 열렸습니다. 이 방법을 사용하면 다른 모듈이 어떤 방식으로 동일한 패키지를 열었고, 개봉되지 않은 패키지를 열 수 없다면이 방법은 모듈을 다른 모듈 권한으로 전달할 수 있습니다.
그러나 동시에 좋은 소식은 다음과 같습니다. Java 9는 Java 8만큼 갈라지기가 쉽지 않습니다. 적어도이 취약점은 닫힙니다. Java는 장난감뿐만 아니라 전문적인 수준으로 발전하기 시작한 것 같습니다 (번역가의 노트 : 누가 Java가 장난감이라고 말했습니까?). 가까운 시일 내에 RPG 및 COBOL 언어로 프로젝트를 Java로 매우 심각하게 마이그레이션 할 수 있습니다. (미안 해요, 농담 이었어)
요약
위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.
이 기사는 https://dzone.com/articles/hacking-the-integercache-in-java-9에서 번역됩니다