2010-12-01 9 views

Antwort

0

Abholen in der LocalVariablesSorter.visitLocalVariable Methode.

+0

Ich habe mit visiLocalVariable zuvor versucht, aber ich möchte alle Zugriffe auf Variablen überwachen und visitLocalVariable wurde nur aufgerufen, wenn eine lokale Variable – tomermes

+0

Recht erklärt wurde. Sie müssen eine Zuordnung vom Index zum Variablennamen selbst pflegen (basierend auf den Aufrufen von visitLocalvariable), wenn Sie dies in einem Besuchermuster verwenden möchten. – aioobe

+0

Natürlich. Vielen Dank. – tomermes

2

ich den Code unten bin mit:

private LocalVariableNode getLocalVariableNode(VarInsnNode varInsnNode, MethodNode methodNode) { 
     int varIdx = varInsnNode.var; 
     int instrIdx = getInstrIndex(varInsnNode); 
     List<?> localVariables = methodNode.localVariables; 
     for (int idx = 0; idx < localVariables.size(); idx++) { 
      LocalVariableNode localVariableNode = (LocalVariableNode) localVariables.get(idx); 
      if (localVariableNode.index == varIdx) { 
       int scopeEndInstrIndex = getInstrIndex(localVariableNode.end); 
       if (scopeEndInstrIndex >= instrIdx) { 
        // still valid for current line 
        return localVariableNode; 
       } 
      } 
     } 
     throw new RuntimeException("Variable with index " + varIdx + " and scope end >= " + instrIdx 
       + " not found for method " + methodNode.name + "!"); 
    } 

Das allgemeine Problem ist, dass der Index der lokalen Variablen wiederverwendet werden können. Sie müssen also sicherstellen, dass Sie den richtigen LocalVariableNode für einen bestimmten Index erhalten. Um dies zu tun, müssen Sie sicherstellen, dass die angegebene Variable immer noch an der Stelle gültig ist, an der sie verwendet wird. Das Problem ist, dass Sie nicht die Zeilennummern verwenden können, weil

  1. die Startposition der nächsten Codezeile nach die Variable definiert wurde, ist. Da leere Zeilen und Kommentare ignoriert werden, kann dies jede folgende Zeile sein. Da der Code jedoch eine vorhandene Variable wiederverwenden kann, könnte dies auch eine beliebige Zeile vor der aktuellen Zeile sein.

  2. Die Endposition kann zeilenweise vor der Startposition liegen (z. B. in einer Schleife).

  3. Der Code wurde möglicherweise ohne Zeileninformationen kompiliert.

Sie müssen also Anweisungsindex verwenden, der immer korrekt ist. Aber es ist eine interne Information in AbstractInsnNode, auf die von außen nicht zugegriffen werden kann. Um dieses Problem zu umgehen, verwende ich den folgenden Code, der offensichtlich die Kapselung unterbricht und aus mehreren Gründen nicht empfehlenswert ist. Wenn Sie etwas besseres finden, lassen Sie es mich wissen! In der Zwischenzeit arbeitet das:

private int getInstrIndex(AbstractInsnNode insnNode) { 
     try { 
      Field indexField = AbstractInsnNode.class.getDeclaredField("index"); 
      indexField.setAccessible(true); 
      Object indexValue = indexField.get(insnNode); 
      return ((Integer) indexValue).intValue(); 
     } catch (Exception exc) { 
      throw new RuntimeException(exc); 
     } 
    }