1 19 20 package org.netbeans.modules.debugger.jpda; 21 22 import com.sun.jdi.AbsentInformationException; 23 import com.sun.jdi.IncompatibleThreadStateException; 24 import com.sun.jdi.Location; 25 import com.sun.jdi.Method; 26 import com.sun.jdi.ReferenceType; 27 import com.sun.jdi.StackFrame; 28 import com.sun.jdi.ThreadReference; 29 30 import java.lang.reflect.InvocationTargetException ; 31 import java.util.ArrayList ; 32 import java.util.HashMap ; 33 import java.util.Iterator ; 34 import java.util.List ; 35 import java.util.Map ; 36 import java.util.logging.Level ; 37 import java.util.logging.Logger ; 38 39 import org.netbeans.api.debugger.DebuggerManager; 40 import org.netbeans.api.debugger.Session; 41 import org.netbeans.spi.debugger.jpda.EditorContext; 42 import org.netbeans.spi.debugger.jpda.EditorContext.Operation; 43 44 49 public class ExpressionPool { 50 51 private static final boolean IS_JDK_16 = !System.getProperty("java.version").startsWith("1.5"); private static Logger logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.step"); 54 private Map <ExpressionLocation, Expression> expressions = new HashMap <ExpressionLocation, Expression>(); 55 56 59 ExpressionPool() { 60 } 61 62 public synchronized Expression getExpressionAt(Location loc, String url) { 63 ExpressionLocation exprLocation = new ExpressionLocation(loc.method(), loc.lineNumber()); 64 if (!expressions.containsKey(exprLocation)) { 65 Expression expr = createExpressionAt(loc, url); 66 expressions.put(exprLocation, expr); 67 } 68 return expressions.get(exprLocation); 69 } 70 71 77 public void cleanUnusedExpressions(ThreadReference thr) { 78 synchronized (this) { 79 if (expressions.size() == 0) { 80 return ; 81 } 82 } 83 List <StackFrame> stackFrames; 84 try { 85 stackFrames = thr.frames(); 86 synchronized (this) { 87 for (Iterator <ExpressionLocation> locIt = expressions.keySet().iterator(); locIt.hasNext(); ) { 88 ExpressionLocation exprLoc = locIt.next(); 89 Method method = exprLoc.getMethod(); 91 int line = exprLoc.getLine(); 92 for (Iterator <StackFrame> it = stackFrames.iterator(); it.hasNext(); ) { 93 StackFrame sf = it.next(); 94 if (method.equals(sf.location().method())) { 95 method = null; 97 break; 98 } 99 } 100 if (method != null) { 101 locIt.remove(); 102 } 103 } 104 } 105 } catch (IncompatibleThreadStateException ex) { 106 } 108 } 109 110 private Expression createExpressionAt(Location loc, String url) { 111 ReferenceType clazzType = loc.declaringType(); 112 final Method method = loc.method(); 113 final byte[] bytecodes = method.bytecodes(); 114 byte[] constantPool = new byte[0]; 115 String JDKVersion = System.getProperty("java.version"); if (IS_JDK_16) { 117 try { java.lang.reflect.Method constantPoolMethod = 119 clazzType.getClass().getMethod("constantPool", new Class [0]); try { 121 constantPool = (byte[]) constantPoolMethod.invoke(clazzType, new Object [0]); 122 } catch (IllegalArgumentException ex) { 123 } catch (InvocationTargetException ex) { 124 } catch (IllegalAccessException ex) { 125 } 126 } catch (SecurityException ex) { 127 } catch (NoSuchMethodException ex) { 128 } 129 } 130 final byte[] theConstantPool = constantPool; 131 Session currentSession = DebuggerManager.getDebuggerManager().getCurrentSession(); 132 final String language = currentSession == null ? null : currentSession.getCurrentLanguage(); 133 134 int line = loc.lineNumber(language); 135 136 Operation[] ops = EditorContextBridge.getOperations( 137 url, line, new EditorContext.BytecodeProvider() { 138 public byte[] constantPool() { 139 return theConstantPool; 140 } 141 142 public byte[] byteCodes() { 143 return bytecodes; 144 } 145 146 public int[] indexAtLines(int startLine, int endLine) { 147 return getIndexesAtLines(method, language, startLine, endLine); 148 } 149 150 }); 151 if (ops == null) { 152 logger.log(Level.FINE, "Unsuccessfull bytecode matching."); 153 return null; 154 } 155 if (ops.length == 0) { return null; 157 } 158 Location[] locations = new Location[ops.length]; 159 for (int i = 0; i < ops.length; i++) { 160 int codeIndex = ops[i].getBytecodeIndex(); 161 locations[i] = method.locationOfCodeIndex(codeIndex); 162 if (locations[i] == null) { 163 logger.log(Level.FINE, "Location of the operation not found."); 164 return null; 165 } 166 } 167 Expression expr = new Expression(new ExpressionLocation(method, line), ops, locations); 168 return expr; 169 } 170 171 private static int[] getIndexesAtLines(Method method, String language, int startLine, int endLine) { 172 try { 173 List <Location> startLocations; 174 int startlocline = 0; 175 int endlocline; 176 do { 177 startLocations = method.locationsOfLine(language, null, startLine - startlocline++); 178 } while (startLocations.isEmpty()); 179 if (endLine > startLine - (startlocline - 1)) { 180 endlocline = 0; 181 } else { 182 endlocline = 1; 183 } 184 startLine -= (startlocline - 1); 185 endLine += endlocline; 186 } catch (AbsentInformationException aiex) { 187 logger.log(Level.FINE, aiex.getLocalizedMessage()); 188 return null; 189 } 190 List <int[]> indexes = new ArrayList <int[]>(); 191 List <Location> allLocations; 192 try { 193 allLocations = method.allLineLocations(language, null); 194 } catch (AbsentInformationException aiex) { 195 logger.log(Level.FINE, aiex.getLocalizedMessage()); 196 return null; 197 } 198 int startIndex = -1; 199 for (Location l : allLocations) { 200 int line = l.lineNumber(language); 201 if (startIndex == -1 && startLine <= line && line < endLine) { 202 startIndex = (int) l.codeIndex(); 203 } else if (startIndex >= 0) { 204 indexes.add(new int[] { startIndex, (int) l.codeIndex() }); 205 startIndex = -1; 206 } 207 } 208 if (indexes.size() == 0) { 209 if (startIndex >= 0) { 210 return new int[] { startIndex, method.bytecodes().length }; 212 } 213 return null; 214 } else if (indexes.size() == 1) { 215 return indexes.get(0); 216 } else { 217 int[] arr = new int[2*indexes.size()]; 218 for (int i = 0; i < indexes.size(); i++) { 219 arr[2*i] = indexes.get(i)[0]; 220 arr[2*i + 1] = indexes.get(i)[1]; 221 } 222 return arr; 223 } 224 } 225 226 228 public static final class Expression { 229 230 private ExpressionLocation location; 231 private Operation[] operations; 232 private Location[] locations; 233 234 Expression(ExpressionLocation location, Operation[] operations, Location[] locations) { 235 this.location = location; 236 this.operations = operations; 237 this.locations = locations; 238 } 239 240 public Operation[] getOperations() { 241 return operations; 242 } 243 244 public Location[] getLocations() { 245 return locations; 246 } 247 248 public int findNextOperationIndex(int codeIndex) { 249 for (int i = 0; i < operations.length; i++) { 250 int operationIndex = operations[i].getBytecodeIndex(); 251 if (operationIndex > codeIndex) { 252 return i; 253 } 254 } 255 return -1; 256 } 257 258 int[] findNextOperationIndexes(int codeIndex) { 259 for (int i = 0; i < operations.length; i++) { 260 int operationIndex = operations[i].getBytecodeIndex(); 261 if (operationIndex == codeIndex) { 262 List <Operation> nextOperations = operations[i].getNextOperations(); 263 if (!nextOperations.isEmpty()) { 264 int l = nextOperations.size(); 265 int[] indexes = new int[l]; 266 for (int ni = 0; ni < l; ni++) { 267 Operation op = nextOperations.get(ni); 268 int j; 269 for (j = 0; j < operations.length; j++) { 270 if (op == operations[j]) break; 271 } 272 if (j < operations.length) { 273 indexes[ni] = j; 274 } else { 275 indexes[ni] = -1; 276 } 277 } 278 return indexes; 279 } 280 } 281 if (operationIndex > codeIndex) { 282 return new int[] { i }; 283 } 284 } 285 return null; 286 } 287 288 OperationLocation[] findNextOperationLocations(int codeIndex) { 289 for (int i = 0; i < operations.length; i++) { 290 int operationIndex = operations[i].getBytecodeIndex(); 291 if (operationIndex == codeIndex) { 292 List <Operation> nextOperations = operations[i].getNextOperations(); 293 if (!nextOperations.isEmpty()) { 294 int l = nextOperations.size(); 295 OperationLocation[] opLocations = new OperationLocation[l]; 296 for (int ni = 0; ni < l; ni++) { 297 Operation op = nextOperations.get(ni); 298 int j; 299 for (j = 0; j < operations.length; j++) { 300 if (op == operations[j]) break; 301 } 302 if (j < operations.length) { 303 opLocations[ni] = new OperationLocation(operations[j], locations[j], j); 305 } else { 306 int ci = op.getBytecodeIndex(); 307 Location loc = location.getMethod().locationOfCodeIndex(ci); 308 if (loc == null) { 309 logger.log(Level.FINE, "Location of the operation not found."); 310 return null; 311 } 312 opLocations[ni] = new OperationLocation(op, loc, -1); 314 } 315 } 316 return opLocations; 317 } 318 } 319 if (operationIndex > codeIndex) { 320 return new OperationLocation[] { new OperationLocation( 321 operations[i], 322 locations[i], 323 i 324 ) }; 325 } 326 } 327 return null; 328 } 329 330 } 331 332 public static final class ExpressionLocation { 333 334 private Method method; 335 private int line; 336 337 public ExpressionLocation(Method method, int line) { 338 this.method = method; 339 this.line = line; 340 } 341 342 public Method getMethod() { 343 return method; 344 } 345 346 public int getLine() { 347 return line; 348 } 349 350 public boolean equals(Object obj) { 351 if (!(obj instanceof ExpressionLocation)) { 352 return false; 353 } 354 return ((ExpressionLocation) obj).line == line && ((ExpressionLocation) obj).method.equals(method); 355 } 356 357 public int hashCode() { 358 return method.hashCode() + line; 359 } 360 361 } 362 363 public static final class OperationLocation { 364 365 private Operation op; 366 private Location loc; 367 private int index; 368 369 OperationLocation(Operation op, Location loc, int index) { 370 this.op = op; 371 this.loc = loc; 372 this.index = index; 373 } 374 375 public Operation getOperation() { 376 return op; 377 } 378 379 public Location getLocation() { 380 return loc; 381 } 382 383 public int getIndex() { 384 return index; 385 } 386 387 } 388 389 } 390 | Popular Tags |