JVM 의 StringTable 에 대한 자세 한 설명

6223 단어 JVMStringTable
무엇
문자열 상수 탱크 는 JVM 에서 중요 한 구조 로 JVM 이 실 행 될 때 발생 하 는 문자열 을 저장 합 니 다.JDK 7 이전에 방법 영역 에 저 장 된 것 은 문자열 상수 입 니 다.문자열 상수 풀 은 JDK 7 에서 더미 로 옮 기기 시 작 했 습 니 다.이에 따라 문자열 상수 외 에 문자열 인용 도 저장 할 수 있 습 니 다(더미 에 있 는 문자열 상수 가 편리 하기 때문에 인용 을 저장 할 수 있 습 니 다).이 때문에 많은 문자열 의 작업 이 JDK 7 과 이전 버 전에 서 실 행 된 것 과 다른 결과 입 니 다.문자열 과 관련 된 문제 가 이렇게 현혹 적 인 이유 중 하나 다.
하층
String:JDK 9 이전에 String 바 텀 은 char 배열 로 문자열 데 이 터 를 저장 하고 JDK 9 부터 by te 배열+인 코딩 으로 char 배열 을 대체 합 니 다.이것 은 공간 을 절약 하기 위해 서 입 니 다.인 코딩 된 데이터 가 공간 을 차지 하 는 것 이 다 르 기 때문에 많은 단위 의 데 이 터 는 하나의 by te(8 바이트)만 있 으 면 저장 할 수 있 습 니 다.char(16 바이트)를 사용 하면 남 은 공간 을 낭비 할 수 있다.
문자열 상수 탱크:아래쪽 에 HashTable 을 사용 하여 문자열 을 저장 합 니 다.JDK 6 HashTable 의 배열 길 이 는 1006 이 고 JDK 7 은 60013 이 되 기 시 작 했 습 니 다.이것 은 저장 문자열 이 너무 많아 서 링크 의 길이 가 너무 길 어 조회 효율 이 떨 어 지 는 것 을 피하 기 위해 서 입 니 다.인자-XX:StringTableSize=을 사용 하여 StringTable 배열 의 길 이 를 설정 할 수 있 습 니 다.
일반적인 문제 문자열 추가
1.문자열 상수 에 대해 컴 파일 러 는 직접 추가 로 최적화 합 니 다.
예 를 들 어 String ss="a"+"b"는 컴 파 일 러 의 최적화 아래 실제 적 으로"ab"문자열 만 생 성 합 니 다.
그리고 final String s1="a";String s2=s1+"b"는 문자열"a"를 만 드 는 것 외 에"ab"만 생 성 합 니 다.
작업 관련 문자열 은 다음 과 같 습 니 다:

문자열'a','ab'만 입력 작업(ldc)을 볼 수 있 습 니 다.
2.문자열 변 수 를 포함 하 는 추가 에 대해 문자열 상수 탱크 에 해당 하 는 문자열 을 만 들 지 않 습 니 다.
String s1="a";String s2=s1+"b",실행 후 문자열 상수 탱크 에는"a","b"문자열 만 포 함 됩 니 다.
s1+"b"에 대해 서 는 바이트 코드 작업 입 니 다.

이 를 통 해 알 수 있 듯 이 추가 작업 은 실제로 StringBuilder 의 append 방법 으로 문자열 을 연결 한 다음 에 toString 방법 으로 반환 값 을 가 져 와 출력 을 저장 하 는 것 입 니 다.그 동안 풀 에 들 어가 지 않 았 습 니 다(ldc).
이 를 통 해 얻 은 최적화 제안:비상 용량 을 포함 하 는 문자열 을 한 번 실행 할 때마다 StringBuilder 대상 을 만 들 었 기 때문에 여러 번 의 연결 이 필요 하 다 면 StringBuilder 대상 을 직접 만 들 고 하나의 StringBuilder 대상 을 사용 하여 문자열 연결 을 하여 여러 대상 을 만 드 는 것 이 효율 을 떨 어 뜨리 지 않도록 할 수 있 습 니 다.
대상 생 성 수량
대상,new 대상 및 문자열 대상 포함.
1.String ss=new String("ab")에 대해 이 과정 은 먼저 문자열 상수 탱크 에"ab"문자열 상수 를 만 든 다음 더미 에 new String()대상 을 만 듭 니 다.이 대상 에 상수 탱크 에"ab"의 주소 정 보 를 저장 하고 마지막 으로 스 택 에 부분 변수 ss 를 만 들 고 더미 에 만 든 대상 주 소 를 저장 합 니 다.그래서 쌓 여 있 는 대상 과 문자열 상수 탱크 의 대상 을 만 들 었 습 니 다.
2、new String("a") + new String("b")。엄 밀 히 보면 여섯 개의 대상 을 만 들 었 다.
우선 new String("a")과 new String("b")은 두 개의 대상 을 만 든 것 으로 나 뉜 다.둘 을 더 하면 StringBuilder 대상 을 만 들 고 StringBuilder.toString()방법 에서 도 String 대상 을 만 듭 니 다.

3、String s1 = "a", String s2 = "b", String s3 = "a" + "b" + s1 + "c" + s2;대응 하 는 바이트 번 호 는 다음 과 같 습 니 다.

문자열 상수 탱크 에는'a','b','ab','c'등 네 개의 문자열 대상 이 있 습 니 다.처음에 s1,s2 의 할당 으로 인해'a','b'를 각각 문자열 상수 풀 에 추가 한 다음 에 세 번 째 단 계 를 실행 합 니 다.운행 순 서 는 왼쪽 에서 오른쪽으로'a'+'b'를 먼저 실행 합 니 다.두 개 모두 상수 이기 때문에 컴 파일 러 의 최적화 로'ab'로 돌아 갑 니 다.그리고 계 산 된 두 매개 변 수 는 모두 상수 이기 때문에 문자열 상수 풀 을 직접 넣 습 니 다.그 다음 에 변수 s1 과 추가 되 기 때문에 StringBuilder 의 append 방법 을 호출 하여 얻 은 결 과 를 국부 변수 표 에 저장 하기 때문에 상수'c'를 도입 합 니 다.상수 이기 때문에 문자열 상수 풀 을 도입 한 다음 에 앞의 조합 에서 얻 은 결과 와 다시 연결 하고 마지막 에 변수 s2 와 추가 합 니 다.상수 가 아니 기 때문에 결 과 를 문자열 상수 탱크 에 넣 지 않 습 니 다.
그 밖 에 상기 세 가지 상황 은 초기 상황,즉 문자열 상수 탱크 에 추가 할 문자열 이 없 을 때의 장면 입 니 다.문자열 상수 탱크 에 추가 할 문자열 이 미리 포함 되 어 있 으 면 상수 탱크 에 대응 하 는 문자열 주 소 를 호출 자 에 게 되 돌려 줍 니 다.예 를 들 어 String s1="a"는 상수 탱크 에"a"가 없 을 때 만 든 대상 이 1 개 이 고 상수 탱크 에 이미 존재 하면 주 소 를 s1 에 직접 되 돌려 줍 니 다.그럼 만 든 대상 은 0 개 입 니 다.
intern()과 문자열 의 동일 한 판단
intern()방법 은 String 류 의 native 방법 입 니 다.이 방법 을 사용 하 는 문자열 대상 을 문자열 상수 탱크 에 추가 한 다음 상수 탱크 에 저 장 된 값 을 되 돌려 주 는 역할 을 합 니 다.처음에 말 했 듯 이 JDK 7 에서 문자열 상수 풀 을 시작 하면 문자열 인용 을 저장 할 수 있 고 문자열 을 조작 하 는 과정 이 다 르 기 때문에 서로 다른 결 과 를 얻 을 수 있 습 니 다.
intern()방법의 실행:
1.6 및 이전:현재 문자열 의 상수 풀 을 상수 풀 에 추가 하려 고 합 니 다.상수 풀 이 존재 하면 주소 값 을 되 돌려 줍 니 다.존재 하지 않 으 면 상수 탱크 를 넣 고 가입 위치 에 있 는 주소 값 을 되 돌려 줍 니 다.
1.7 시작:현재 문자열 의 상수 를 상수 탱크 에 넣 으 려 고 시도 합 니 다.존재 하면 주소 값 을 되 돌려 줍 니 다.존재 하지 않 으 면 현재 String 문자열 의 주소 값 을 저장 합 니 다.
다음은 하나의 예 로 JDK 7 과 JDK 7 이전에 다음 코드 가 각각 어떤 결 과 를 실 행 했 는 지 설명 한다.

@Test
 public void test1(){
  String s = new String("1");
  s.intern();
  String s2 = "1";
  System.out.println(s == s2);


  String s3 = new String("1") + new String("1");
  s3.intern();
  String s4 = "11";
  System.out.println(s3 == s4);
 }
먼저 결론 을 말 하 다.
JDK 7 이전:false,false.
JDK 7 및 그 후:false,true.
원인:
1.먼저 위의 3----6 줄 을 보 세 요.먼저 세 번 째 줄 은 문자열 상수 탱크 에'1'을 추가 한 다음 에 더미 에 대상 을 만 들 고'1'이 상수 탱크 에 있 는 주 소 를 저장 한 다음 에 국부 변수 표 에 s 저장 더미 에 있 는 대상 의 주 소 를 추가 합 니 다.그 다음 에 네 번 째 줄 을 실행 합 니 다.이때 s 가 가리 키 는 문자열 은 상수 풀 에 있 기 때문에 이 단 계 는 유효 하지 않 습 니 다.다섯 번 째 줄 은 상수 풀 에'1'이 존재 하기 때문에 JDK 7 이나 이전에 실 행 된 논 리 는 똑 같 습 니 다.'1'이 상수 풀 에 있 는 주 소 를 s2 에 직접 되 돌려 줍 니 다.그리고 s 가 가리 키 는 것 은 더미 속 의 대상 이 고 s2 가 가리 키 는 것 은 상수 탱크 의 문자열 상수 이기 때문에 JDK 7 이 든 이전 이 든 모두 false 라 고 판단 합 니 다.
2.그리고 아래 9-12 줄 을 보 세 요.앞에서 상수 탱크 에'1'을 추 가 했 기 때문에 9 번 째 줄 은 주 소 를 되 돌려 주 고 추가 작업 을 수행 하여 문자열'11'을 만 듭 니 다.이때 상수 탱크 에 추가 하지 않 고 10 번 째 줄 을 실행 합 니 다.상수 탱크 에'11'이 존재 하지 않 기 때문에 JDK 7 은 상수 탱크 에 직접 가입 하고 JDK 7 과 이후 에는'11'의 주 소 를 상수 탱크 에 직접 저장 합 니 다.s3 는 변 하지 않 습 니 다.아니면 상수 탱크 밖의'11'주소 값 을 저장 한 것 입 니까?그리고 11 줄 을 실행 합 니 다.상수 탱크 에'11'이 존재 하기 때문에 s4 는'11'의 주소 값 을 되 돌려 주 는 것 입 니 다.다른 것 은 JDK 7 이전에 상수 탱크 에'11'상수 가 저장 되 어 있 기 때문에 상수 탱크 의 주소 값 을 되 돌려 줍 니 다.JDK 7 및 이후 상수 탱크 는 상수 탱크 밖의'11'주소 값 을 저장 하기 때문에 연못 밖의 주소 값 을 되 돌려 줍 니 다.그래서 최종 판단 은 JDK 7 이전 에는 false 였 고 JDK 7 부 터 는 true 였 다.
JVM 의 StringTable 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 JVM 의 StringTable 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기