2014-10-21 4 views
1

Я просматриваю результаты Javap. Например:Java & Javap: как определить, какой объект получает Invokevirtual

Этот код

final Foo foo = new Foo(1,2); 
    ... 
    new Callable<Integer>() 
    { 
     @Override 
     public Integer call() throws Exception 
     { 
      return foo.doSomething(); 
     } 

Формирует:

 jvmOperations": [{ 
      "byteOffset": 0, 
      "constantPoolIndex": null, 
      "opCode": 42, 
      "opCodeName": "aload_0", 
      "type": null, 
      "tagName": null, 
      "tagValue": null 
     }, { 
      "byteOffset": 1, 
      "constantPoolIndex": null, 
      "opCode": 180, 
      "opCodeName": "getfield", 
      "type": null, 
      "tagName": "Field", 
      "tagValue": "val$foo:Lcom/example/graph/demo/Foo;" 
     }, { 
      "byteOffset": 4, 
      "constantPoolIndex": null, 
      "opCode": 182, 
      "opCodeName": "invokevirtual", 
      "type": null, 
      "tagName": "Method", 
      "tagValue": "com/example/graph/demo/Foo.doSomething:()Ljava/lang/Integer;" 
     }, { 
      "byteOffset": 7, 
      "constantPoolIndex": null, 
      "opCode": 176, 
      "opCodeName": "areturn", 
      "type": null, 
      "tagName": null, 
      "tagValue": null 
     }] 

Так я вижу, что объект идентифицируется в данном случае val$foo. А в метаданных класса

"classMetaData": { 
     "classId": "com/example/Main$1.class", 
     "sourceName": "Main.java", 
     "isInterface": false, 
     "isClass": true, 
     "accessModifiers": ["final"], 
     "superClassName": "java/lang/Object", 
     "implementedInterfaces": ["java/util/concurrent/Callable"], 
     "jreTargetVersion": "51.0", 
     "fields": ["val$foo"], 
     "fieldModifiers": { 
      "val$foo": ["final"] 
     }, 
     "methodInformationMap": {}, 
     "interface": false, 
     "class": true 
    }, 

Но теперь я хочу, чтобы узнать больше об исходном объекте foo. Например, я знаю, что есть эти данные в одном из своих полей:

 { 
      "byteOffset": 37, 
      "constantPoolIndex": null, 
      "opCode": 18, 
      "opCodeName": "ldc", 
      "type": null, 
      "tagName": "String", 
      "tagValue": "NODE-1" 
     }, 

Как виртуальная машина знать, какие val$foo очков?

+0

Виртуальная машина Java знает, что VAL $ foo указывает на Foo объект (или некоторый подкласс Foo), потому что это так объявлено. И метод, вызываемый фактически, зависит от класса объекта, фактически используемого для invokevirtual. –

ответ

2

Вам нужно немного больше контекста, чтобы отслеживать ценность JVM-магазинов для foo.

Предполагая foo является локальной переменной

  1. new Foo(1,2); вызывается
  2. Результат, значение ссылки на экземпляр, копируется и хранится в локальной переменной foo
  3. ... вещи ...
  4. Вызывается анонимный конструктор классов для создания нового экземпляра
  5. В качестве части своего конструктора копия значения th е локальная переменная foo извлекается и помещается в стек
  6. Это значение извлекается из стека и присвоенного этому val$foo поле анонимного класса (это закрытие над этой переменной)
  7. ... материал ...
  8. Когда foo.something() вызывается, виртуальная машина извлекает значение поля val$foo экземпляра анонимного класса
  9. Виртуальная машина Java разыменовывает это значение, чтобы получить объект и вызывает метод на нем
+0

Спасибо Sotirios, оказывается, что часть данных, которые мне нужны, также может быть в постоянном пуле. –