Skip to content

Commit 1e0702b

Browse files
committed
Refactor String model class
Refactors String model class based on JDK 10.0.1 source. * Add support for JEP 254: Compact Strings, which fixes [junit] java.lang.NoSuchFieldError: java.lang.String.COMPACT_STRINGS * Refactor String#contentEquals(java.lang.CharSequence) as the current implementation only handles UTF16
1 parent 5145473 commit 1e0702b

File tree

1 file changed

+54
-52
lines changed

1 file changed

+54
-52
lines changed

src/classes/modules/java.base/java/lang/String.java

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public final class String
6363

6464
private static final long serialVersionUID = -6849794470754667710L;
6565

66+
static final boolean COMPACT_STRINGS;
67+
static {
68+
COMPACT_STRINGS = true;
69+
}
6670

6771
private static final ObjectStreamField[] serialPersistentFields =
6872
new ObjectStreamField[0];
@@ -79,18 +83,13 @@ public String(String original) {
7983
}
8084

8185
public String(char value[]) {
82-
this(value, 0, value.length, null);
86+
this(value, 0, value.length);
8387
}
8488

85-
public String(char value[], boolean share) {
86-
this(value, 0, value.length, null);
87-
}
88-
8989
public String(char value[], int offset, int count) {
9090
String proxy=init(value,offset,count);
9191
this.value=proxy.value;
9292
this.coder=proxy.coder;
93-
this.hash=proxy.hash;
9493
}
9594

9695
private native String init(char[] value, int offset, int count);
@@ -99,7 +98,6 @@ public String(int[] codePoints, int offset, int count) {
9998
String proxy=init(codePoints,offset,count);
10099
this.value=proxy.value;
101100
this.coder=proxy.coder;
102-
this.hash=proxy.hash;
103101
}
104102

105103
private native String init(int[] codePoints, int offset, int count);
@@ -119,13 +117,10 @@ public String(byte ascii[], int hibyte) {
119117
this(ascii, hibyte, 0, ascii.length);
120118
}
121119

122-
123-
124120
public String(byte bytes[], int offset, int length, String charsetName){
125121
String proxy=init(bytes,offset,length,charsetName);
126122
this.value=proxy.value;
127123
this.coder=proxy.coder;
128-
this.hash=proxy.hash;
129124
}
130125

131126
private native String init(byte bytes[], int offset, int length, String charsetName);
@@ -151,8 +146,7 @@ public String(byte x[], int offset, int length, Charset cset) {
151146
this.coder = result.coder;
152147
}
153148

154-
public String(byte bytes[], String charsetName)
155-
throws UnsupportedEncodingException {
149+
public String(byte bytes[], String charsetName) throws UnsupportedEncodingException {
156150
this(bytes, 0, bytes.length, charsetName);
157151
}
158152

@@ -164,42 +158,30 @@ public String(byte bytes[], int offset, int length) {
164158
String proxy=init(bytes,offset,length);
165159
this.value=proxy.value;
166160
this.coder=proxy.coder;
167-
this.hash=proxy.hash;
168161
}
169162

170-
171163
private native String init(byte bytes[], int offset, int length);
172164

173165
public String(byte bytes[]) {
174166
this(bytes, 0, bytes.length);
175167
}
176168

177-
178169
public String(StringBuffer x) {
179170
this(x.toString());
180171
}
181172

182-
183173
public String(StringBuilder x) {
184174
this.value = Arrays.copyOf(x.getValue(), x.length());
185175
this.coder = x.coder;
186176
}
187177

188178
String(char[] value, int off, int len, Void sig) {
189-
if (len == 0) {
190-
this.value = "".value;
191-
this.coder = "".coder;
192-
} else {
193-
byte[] val = StringUTF16.compress(value, off, len);
194-
if (val != null) {
195-
this.value = val;
196-
this.coder = LATIN1;
197-
return;
198-
}
179+
this(value, off, len);
180+
}
199181

200-
this.coder = UTF16;
201-
this.value = StringUTF16.toBytes(value, off, len);
202-
}
182+
String(byte[] value, byte coder) {
183+
this.value = value;
184+
this.coder = coder;
203185
}
204186

205187
@Deprecated
@@ -213,32 +195,21 @@ public int length() {
213195
public boolean isEmpty() {
214196
return value.length == 0;
215197
}
216-
@Override
217-
public char charAt(int index) {
218-
if ((index < 0) || (index >= value.length)) {
219-
throw new StringIndexOutOfBoundsException(index);
220-
}
221-
return this.isLatin1() ? StringLatin1.charAt(this.value, index) : StringUTF16.charAt(this.value, index);
222-
}
223198

199+
native public char charAt(int index);
224200
native public int codePointAt(int index);
225201
native public int codePointBefore(int index);
226202
native public int codePointCount(int beginIndex, int endIndex);
227203
native public int offsetByCodePoints(int index, int codePointOffset);
228204
native public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin);
229-
native void getChars(char dst[], int dstBegin);
230205

231206
@Deprecated
232207
native public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin);
233-
native public byte[] getBytes(String charsetName)
234-
throws UnsupportedEncodingException;
208+
native public byte[] getBytes(String charsetName) throws UnsupportedEncodingException;
235209

236210
public byte[] getBytes(Charset x){
237-
// No Charset model.
238-
if (x == null){
239-
throw new NullPointerException();
240-
}
241-
return StringCoding.encode(x, this.coder, this.value);
211+
if (x == null) throw new NullPointerException();
212+
return StringCoding.encode(x, coder(), value);
242213
}
243214

244215
native public byte[] getBytes();
@@ -251,6 +222,26 @@ public boolean contentEquals(StringBuffer stringBuffer){
251222
}
252223
}
253224

225+
private boolean nonSyncContentEquals(AbstractStringBuilder abstractStringBuilder) {
226+
int len = length();
227+
if (len != abstractStringBuilder.length()) {
228+
return false;
229+
}
230+
byte v1[] = value;
231+
byte v2[] = abstractStringBuilder.getValue();
232+
if (coder() == abstractStringBuilder.getCoder()) {
233+
int n = v1.length;
234+
for (int i = 0; i < n; i++) {
235+
if (v1[i] != v2[i]) {
236+
return false;
237+
}
238+
}
239+
} else {
240+
return isLatin1() && StringUTF16.contentEquals(v1, v2, len);
241+
}
242+
return true;
243+
}
244+
254245
native static boolean equals0 (char[] a, char[] b, int len);
255246

256247
/**
@@ -262,21 +253,28 @@ public boolean contentEquals (CharSequence charSequence){
262253
return false;
263254
}
264255

265-
// that should be the common case (String)
266-
if (charSequence.equals(this)){
267-
return true;
256+
// cs is a String
257+
if (charSequence instanceof String) {
258+
return equals(charSequence);
268259
}
269260

270-
// we can do that natively, too
261+
// cs is a StringBuffer, or StringBuilder
271262
if (charSequence instanceof AbstractStringBuilder) {
272-
byte[] val = ((AbstractStringBuilder) charSequence).getValue();
273-
byte coder = ((AbstractStringBuilder) charSequence).getCoder();
274-
assert coder == UTF16 : "Currently only UTF16 is supported for String comparision with an instance of type AbstractStringBuilder";
275-
return StringUTF16.contentEquals(this.value, val, this.length());
263+
if (charSequence instanceof StringBuffer) {
264+
synchronized (charSequence) {
265+
return nonSyncContentEquals((AbstractStringBuilder) charSequence);
266+
}
267+
} else {
268+
return nonSyncContentEquals((AbstractStringBuilder) charSequence);
269+
}
276270
}
277271

278272
// generic CharSequence - expensive
279273
int n = charSequence.length();
274+
if (n != length()) {
275+
return false;
276+
}
277+
280278
byte[] val = this.value;
281279
if (isLatin1()) {
282280
for (int i = 0; i < n; i++) {
@@ -401,6 +399,10 @@ public static String valueOf(char character) {
401399
native public static String valueOf(double d);
402400
public native String intern();
403401

402+
byte coder() {
403+
return COMPACT_STRINGS ? coder : UTF16;
404+
}
405+
404406
private boolean isLatin1() {
405407
return this.coder == LATIN1;
406408
}

0 commit comments

Comments
 (0)