matthiasblaesing commented on code in PR #5299:
URL: https://github.com/apache/netbeans/pull/5299#discussion_r1097864205
##########
java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/ShortenedStrings.java:
##########
@@ -130,7 +213,14 @@ static String getStringWithLengthControl(StringReference
sr) throws InternalExce
try {
ReferenceType st = ObjectReferenceWrapper.referenceType(sr);
ArrayReference sa = null;
+ //only applicable if the string implementation uses a byte[]
instead
+ //of a char[]
+ boolean isUTF16 = false;
+ boolean isCompactImpl = false;
Review Comment:
Please add a comment like:
> JEP 254: Compact Strings after the boolean
that might help people to later understand the intention
##########
java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/ShortenedStrings.java:
##########
@@ -130,7 +213,14 @@ static String getStringWithLengthControl(StringReference
sr) throws InternalExce
try {
ReferenceType st = ObjectReferenceWrapper.referenceType(sr);
ArrayReference sa = null;
+ //only applicable if the string implementation uses a byte[]
instead
+ //of a char[]
+ boolean isUTF16 = false;
+ boolean isCompactImpl = false;
+ int hiByteShift = 0;
+ int lowByteShift = 0;
Review Comment:
Please move these down to the use-site (directly before the if in 318) and
remove the initializer. The if will initialize them.
##########
java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/ShortenedStrings.java:
##########
@@ -92,6 +108,73 @@ public static StringInfo getShortenedInfo(String s) {
}
}
+ private static boolean isLittleEndian(VirtualMachine virtualMachine) {
+ synchronized(isLittleEndianCache){
+ Boolean cached = isLittleEndianCache.get(virtualMachine);
+ if (cached != null){
+ return cached;
+ }
+ List<ReferenceType> possibleClasses = virtualMachine.classesByName(
+ "java.lang.StringUTF16");
+ //If we don't know, we are going to assume little endian encoding.
+ //This should work for most architectures (x86, arm, riscv), but
+ //will result in bogus data on big endian architectures
+ final boolean defaultValue = true;
+ if (possibleClasses.isEmpty()){
+ ClassType ct = (ClassType) virtualMachine.classesByName(
+ "java.lang.Class").iterator().next();
+ Method m = ct.concreteMethodByName("forName",
+ "(Ljava/lang/String;)Ljava/lang/Class;");
+ StringReference referenceString = virtualMachine.mirrorOf(
+ "java.lang.StringUTF16");
+ try {
+ ThreadReference threadReference = virtualMachine.
+ allThreads().get(0);
+ ct.invokeMethod(threadReference, m, Collections.
+ singletonList(referenceString), 0);
+ possibleClasses = virtualMachine.classesByName(
+ "java.lang.StringUTF16");
+ } catch (InvalidTypeException | ClassNotLoadedException |
+ IncompatibleThreadStateException | InvocationException
ex) {
+ Exceptions.printStackTrace(ex);
+ isLittleEndianCache.put(virtualMachine, defaultValue);
+ return defaultValue;
+ }
+ }
+ ReferenceType utf16;
+ if (possibleClasses.size() == 1){
+ utf16 = possibleClasses.get(0);
+ }
+ else {
+ isLittleEndianCache.put(virtualMachine, defaultValue);
+ return defaultValue;
+ }
+ Field hiByteShift;
+ try{
+ hiByteShift = ReferenceTypeWrapper.fieldByName(utf16,
+ "HI_BYTE_SHIFT");
+ }
+ catch (ClassNotPreparedExceptionWrapper | InternalExceptionWrapper
|
+ ObjectCollectedExceptionWrapper |
VMDisconnectedExceptionWrapper e){
+ Exceptions.printStackTrace(e);
+ isLittleEndianCache.put(virtualMachine, defaultValue);
+ return defaultValue;
+ }
+ if (hiByteShift == null){
+ isLittleEndianCache.put(virtualMachine, defaultValue);
+ return defaultValue;
+ }
+ Value val = utf16.getValue(hiByteShift);
Review Comment:
I suggest to switch variable to `hiByteShiftValue`.
##########
java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/ShortenedStrings.java:
##########
@@ -92,6 +108,73 @@ public static StringInfo getShortenedInfo(String s) {
}
}
+ private static boolean isLittleEndian(VirtualMachine virtualMachine) {
+ synchronized(isLittleEndianCache){
+ Boolean cached = isLittleEndianCache.get(virtualMachine);
+ if (cached != null){
+ return cached;
+ }
+ List<ReferenceType> possibleClasses = virtualMachine.classesByName(
+ "java.lang.StringUTF16");
+ //If we don't know, we are going to assume little endian encoding.
+ //This should work for most architectures (x86, arm, riscv), but
+ //will result in bogus data on big endian architectures
+ final boolean defaultValue = true;
+ if (possibleClasses.isEmpty()){
+ ClassType ct = (ClassType) virtualMachine.classesByName(
+ "java.lang.Class").iterator().next();
+ Method m = ct.concreteMethodByName("forName",
+ "(Ljava/lang/String;)Ljava/lang/Class;");
+ StringReference referenceString = virtualMachine.mirrorOf(
+ "java.lang.StringUTF16");
+ try {
+ ThreadReference threadReference = virtualMachine.
+ allThreads().get(0);
+ ct.invokeMethod(threadReference, m, Collections.
+ singletonList(referenceString), 0);
+ possibleClasses = virtualMachine.classesByName(
+ "java.lang.StringUTF16");
+ } catch (InvalidTypeException | ClassNotLoadedException |
+ IncompatibleThreadStateException | InvocationException
ex) {
+ Exceptions.printStackTrace(ex);
+ isLittleEndianCache.put(virtualMachine, defaultValue);
+ return defaultValue;
+ }
+ }
+ ReferenceType utf16;
+ if (possibleClasses.size() == 1){
+ utf16 = possibleClasses.get(0);
+ }
+ else {
+ isLittleEndianCache.put(virtualMachine, defaultValue);
+ return defaultValue;
+ }
+ Field hiByteShift;
Review Comment:
Please follow the naming convention you also used in the other method and
make this `hiByteShiftField`
##########
java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/ShortenedStrings.java:
##########
@@ -171,21 +295,73 @@ static String getStringWithLengthControl(StringReference
sr) throws InternalExce
} else {
assert sa != null;
int l = AbstractObjectVariable.MAX_STRING_LENGTH;
- List<Value> values = ArrayReferenceWrapper.getValues(sa, 0, l);
+ List<Value> values = ArrayReferenceWrapper.getValues(sa, 0,
+ isUTF16 ? (l * 2) : l);
char[] characters = new char[l + 3];
- for (int i = 0; i < l; i++) {
- Value v = values.get(i);
- if (!(v instanceof CharValue)) {
- return "<Unreadable>";
+ if (isCompactImpl) {
+ //java compact string
+ if (!isUTF16) {
+ //we can just cast to char
+ for (int i = 0; i < l; i++) {
+ Value v = values.get(i);
+ if (!(v instanceof ByteValue)) {
+ return ERROR_RESULT;
+ }
+ char c = (char)((ByteValue) v).byteValue();
+ //remove the extended sign
+ c &= 0xFF;
+ characters[i] = c;
+ }
+ }
+ else {
+ //is it little or big endian?
+ if (isLittleEndian(sr.virtualMachine())){
+ hiByteShift = 0;
+ lowByteShift = 8;
+ }
+ else{
+ hiByteShift = 8;
+ lowByteShift = 0;
+ }
+ for (int i = 0; i < l; i++) {
+ int index = i * 2;
+ Value v = values.get(index);
+ if (!(v instanceof ByteValue)) {
+ return ERROR_RESULT;
+ }
+ Value v2 = values.get(index + 1);
+ if (!(v instanceof ByteValue)) {
+ return ERROR_RESULT;
+ }
+ char c1 = (char) ((ByteValue) v).byteValue();
+ char c2 = (char) ((ByteValue) v2).byteValue();
+ //remove the extended sign
+ c1 = (char) (0xFF & c1);
+ c2 = (char) (0xFF & c2);
+ char c = (char)(c1 << hiByteShift |
+ c2 << lowByteShift);
+ // char bigEndianChar = (char) ((c1 << 8) | c2);
+ //char litteEndianChar = (char) ((c2 << 8) | c1);
Review Comment:
Please remove the comment ed code
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists