String fix for Java 10 (PR 35)
stefan-reich opened this issue · 2 comments
stefan-reich commented
Hi,
I am using your library in a Java-based OS to find memory leaks automatically.
One small thing. I believe the library is not fully adapted to Java 10? It generally seems to work, don't get me wrong 👍
The issue I have is with the method org.gridkit.jvmtool.heapdump.HeapWalker.stringValue():
public static String stringValue(Instance obj) {
if (obj == null) {
return null;
}
if (!"java.lang.String".equals(obj.getJavaClass().getName())) {
throw new IllegalArgumentException("Is not a string: " + obj.getInstanceId() + " (" + obj.getJavaClass().getName() + ")");
}
char[] text = null;
int offset = 0;
int len = -1;
for(FieldValue f: obj.getFieldValues()) {
Field ff = f.getField();
if ("value".equals(ff.getName())) {
PrimitiveArrayInstance chars = (PrimitiveArrayInstance) ((ObjectFieldValue)f).getInstance();
text = new char[chars.getLength()];
for(int i = 0; i != text.length; ++i) {
text[i] = ((String)chars.getValues().get(i)).charAt(0);
}
}
// fields below were removed in Java 7
else if ("offset".equals(ff.getName())) {
offset = Integer.valueOf(f.getValue());
}
else if ("count".equals(ff.getName())) {
len = Integer.valueOf(f.getValue());
}
}
if (len < 0) {
len = text.length;
}
return new String(text, offset, len);
}
which clearly is pre-JDK 10 code. Any intention to upgrade this?
Many greetings,
Stefan
BotCompany.de
Edit: In fact, I might just do this myself...
stefan-reich commented
OK, here it goes. Want pull request?
static String stringValue_java10(Instance obj) {
if (obj == null) return null;
if (!"java.lang.String".equals(obj.getJavaClass().getName()))
throw new IllegalArgumentException("Is not a string: " + obj.getInstanceId() + " (" + obj.getJavaClass().getName() + ")");
int UTF16 = 1;
Boolean COMPACT_STRINGS = (Boolean) ( obj.getJavaClass().getValueOfStaticField("COMPACT_STRINGS"));
if (COMPACT_STRINGS == null)
return HeapWalker.stringValue(obj); // We're pre Java 9
Object valueInstance = obj.getValueOfField("value");
PrimitiveArrayInstance chars = (PrimitiveArrayInstance) ( valueInstance);
byte coderField = (byte) ( obj.getValueOfField("coder"));
byte coder = COMPACT_STRINGS ? coderField : (byte) UTF16;
int len = chars.getLength() >> coder;
char[] text = new char[len];
List<String> values = (List) chars.getValues();
if (coder == UTF16)
for (int i = 0; i < text.length; i++)
text[i] = values.get(i).charAt(0);
else
for (int i = 0; i < text.length; i++)
text[i] = (char) Integer.parseInt(values.get(i));
return new String(text);
}
Method reverts to Java 8 method automatically if it's not a Java 10 dump.
stefan-reich commented
Pull request: #35