Fri, 22 Jun 2012 15:39:16 -0700
7177128: SA cannot get correct system properties after 7126277
Summary: Bug fix of 7126277 changed hashing algorithm and also changed key as final field, this led SA unable to set correct value for key. Solution by reading key/value and insert them into the new table.
Reviewed-by: dholmes, mikael
Contributed-by: yumin.qi@oracle.com
agent/src/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java | file | annotate | diff | comparison | revisions |
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java Fri Jun 22 15:35:30 2012 -0700 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java Fri Jun 22 15:39:16 2012 -0700 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -85,6 +85,21 @@ 1.11 this(new ProcImageClassLoader()); 1.12 } 1.13 1.14 + static void debugPrintln(String msg) { 1.15 + if (DEBUG) { 1.16 + System.err.println("DEBUG>" + msg); 1.17 + } 1.18 + } 1.19 + 1.20 + static void debugPrintStackTrace(Exception exp) { 1.21 + if (DEBUG) { 1.22 + StackTraceElement[] els = exp.getStackTrace(); 1.23 + for (int i = 0; i < els.length; i++) { 1.24 + System.err.println("DEBUG>" + els[i].toString()); 1.25 + } 1.26 + } 1.27 + } 1.28 + 1.29 public Object readObject(Oop oop) throws ClassNotFoundException { 1.30 if (oop instanceof Instance) { 1.31 return readInstance((Instance) oop); 1.32 @@ -120,13 +135,96 @@ 1.33 } 1.34 1.35 protected Symbol javaLangString; 1.36 + protected Symbol javaUtilHashtableEntry; 1.37 + protected Symbol javaUtilHashtable; 1.38 + protected Symbol javaUtilProperties; 1.39 + 1.40 + protected Symbol getVMSymbol(String name) { 1.41 + return VM.getVM().getSymbolTable().probe(name); 1.42 + } 1.43 + 1.44 protected Symbol javaLangString() { 1.45 if (javaLangString == null) { 1.46 - javaLangString = VM.getVM().getSymbolTable().probe("java/lang/String"); 1.47 + javaLangString = getVMSymbol("java/lang/String"); 1.48 } 1.49 return javaLangString; 1.50 } 1.51 1.52 + protected Symbol javaUtilHashtableEntry() { 1.53 + if (javaUtilHashtableEntry == null) { 1.54 + javaUtilHashtableEntry = getVMSymbol("java/util/Hashtable$Entry"); 1.55 + } 1.56 + return javaUtilHashtableEntry; 1.57 + } 1.58 + 1.59 + protected Symbol javaUtilHashtable() { 1.60 + if (javaUtilHashtable == null) { 1.61 + javaUtilHashtable = getVMSymbol("java/util/Hashtable"); 1.62 + } 1.63 + return javaUtilHashtable; 1.64 + } 1.65 + 1.66 + protected Symbol javaUtilProperties() { 1.67 + if (javaUtilProperties == null) { 1.68 + javaUtilProperties = getVMSymbol("java/util/Properties"); 1.69 + } 1.70 + return javaUtilProperties; 1.71 + } 1.72 + 1.73 + private void setHashtableEntry(java.util.Hashtable p, Oop oop) { 1.74 + InstanceKlass ik = (InstanceKlass)oop.getKlass(); 1.75 + OopField keyField = (OopField)ik.findField("key", "Ljava/lang/Object;"); 1.76 + OopField valueField = (OopField)ik.findField("value", "Ljava/lang/Object;"); 1.77 + OopField nextField = (OopField)ik.findField("next", "Ljava/util/Hashtable$Entry;"); 1.78 + if (DEBUG) { 1.79 + if (Assert.ASSERTS_ENABLED) { 1.80 + Assert.that(ik.getName().equals(javaUtilHashtableEntry()), "Not a Hashtable$Entry?"); 1.81 + Assert.that(keyField != null && valueField != null && nextField != null, "Invalid fields!"); 1.82 + } 1.83 + } 1.84 + 1.85 + Object key = null; 1.86 + Object value = null; 1.87 + Oop next = null; 1.88 + try { 1.89 + key = readObject(keyField.getValue(oop)); 1.90 + value = readObject(valueField.getValue(oop)); 1.91 + next = (Oop)nextField.getValue(oop); 1.92 + // For Properties, should use setProperty(k, v). Since it only runs in SA 1.93 + // using put(k, v) should be OK. 1.94 + p.put(key, value); 1.95 + if (next != null) { 1.96 + setHashtableEntry(p, next); 1.97 + } 1.98 + } catch (ClassNotFoundException ce) { 1.99 + if( DEBUG) { 1.100 + debugPrintln("Class not found " + ce); 1.101 + debugPrintStackTrace(ce); 1.102 + } 1.103 + } 1.104 + } 1.105 + 1.106 + protected Object getHashtable(Instance oop, boolean isProperties) { 1.107 + InstanceKlass k = (InstanceKlass)oop.getKlass(); 1.108 + OopField tableField = (OopField)k.findField("table", "[Ljava/util/Hashtable$Entry;"); 1.109 + if (tableField == null) { 1.110 + debugPrintln("Could not find field of [Ljava/util/Hashtable$Entry;"); 1.111 + return null; 1.112 + } 1.113 + java.util.Hashtable table = (isProperties) ? new java.util.Properties() 1.114 + : new java.util.Hashtable(); 1.115 + ObjArray kvs = (ObjArray)tableField.getValue(oop); 1.116 + long size = kvs.getLength(); 1.117 + debugPrintln("Hashtable$Entry Size = " + size); 1.118 + for (long i=0; i<size; i++) { 1.119 + Oop entry = kvs.getObjAt(i); 1.120 + if (entry != null && entry.isInstance()) { 1.121 + setHashtableEntry(table, entry); 1.122 + } 1.123 + } 1.124 + return table; 1.125 + } 1.126 + 1.127 public Object readInstance(Instance oop) throws ClassNotFoundException { 1.128 Object result = getFromObjTable(oop); 1.129 if (result == null) { 1.130 @@ -134,11 +232,21 @@ 1.131 // Handle java.lang.String instances differently. As part of JSR-133, fields of immutable 1.132 // classes have been made final. The algorithm below will not be able to read Strings from 1.133 // debuggee (can't use reflection to set final fields). But, need to read Strings is very 1.134 - // important. FIXME: need a framework to handle many other special cases. 1.135 + // important. 1.136 + // Same for Hashtable, key and hash are final, could not be set in the algorithm too. 1.137 + // FIXME: need a framework to handle many other special cases. 1.138 if (kls.getName().equals(javaLangString())) { 1.139 return OopUtilities.stringOopToString(oop); 1.140 } 1.141 1.142 + if (kls.getName().equals(javaUtilHashtable())) { 1.143 + return getHashtable(oop, false); 1.144 + } 1.145 + 1.146 + if (kls.getName().equals(javaUtilProperties())) { 1.147 + return getHashtable(oop, true); 1.148 + } 1.149 + 1.150 Class clz = readClass(kls); 1.151 try { 1.152 result = clz.newInstance(); 1.153 @@ -164,8 +272,8 @@ 1.154 break; 1.155 } catch (Exception exp) { 1.156 if (DEBUG) { 1.157 - System.err.println("Can't create object using " + c); 1.158 - exp.printStackTrace(); 1.159 + debugPrintln("Can't create object using " + c); 1.160 + debugPrintStackTrace(exp); 1.161 } 1.162 } 1.163 } 1.164 @@ -329,8 +437,8 @@ 1.165 arrayObj[ifd.getIndex()] = readObject(field.getValue(getObj())); 1.166 } catch (Exception e) { 1.167 if (DEBUG) { 1.168 - System.err.println("Array element set failed for " + ifd); 1.169 - e.printStackTrace(); 1.170 + debugPrintln("Array element set failed for " + ifd); 1.171 + debugPrintStackTrace(e); 1.172 } 1.173 } 1.174 } 1.175 @@ -348,8 +456,8 @@ 1.176 1.177 private void printFieldSetError(java.lang.reflect.Field f, Exception ex) { 1.178 if (DEBUG) { 1.179 - if (f != null) System.err.println("Field set failed for " + f); 1.180 - ex.printStackTrace(); 1.181 + if (f != null) debugPrintln("Field set failed for " + f); 1.182 + debugPrintStackTrace(ex); 1.183 } 1.184 } 1.185 1.186 @@ -601,7 +709,7 @@ 1.187 return Class.forName(className, true, cl); 1.188 } catch (Exception e) { 1.189 if (DEBUG) { 1.190 - System.err.println("Can't load class " + className); 1.191 + debugPrintln("Can't load class " + className); 1.192 } 1.193 throw new RuntimeException(e); 1.194 }