Вот мой пример кода Java.
package com.test;
import javax.servlet.http.HttpServletRequest;
public class TestASMIns
{
public void process(HttpServletRequest request)
{
String userName;
if(request.getParameterMap().containsKey("username"))
{
userName = request.getParameter("username");
}
else
{
userName = "UNKNOWN";
}
System.out.println(userName);
}
}
В приведенном выше примере локальная переменная userName объявлена внутри тела метода. Инструкция байт-кода AFAIK для приведенного выше кода должна содержать только один LocalVariableNode для переменной 'userName' (поскольку он не объявлен ни в какой внутренней области/блоке). Но инструкция байт-кода для LocalVariableTable содержит повторяющуюся запись для переменной 'userName'. Может кто-нибудь пролить свет на это.
Вот инструкции байт-кода: (сгенерированы с использованием javap)
public void process(javax.servlet.http.HttpServletRequest);
descriptor: (Ljavax/servlet/http/HttpServletRequest;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=2
0: aload_1
1: invokeinterface #16, 1 // InterfaceMethod javax/servlet/http/HttpServletRequest.getParameterMap:()Ljava/util/Map;
6: ldc #22 // String username
8: invokeinterface #24, 2 // InterfaceMethod java/util/Map.containsKey:(Ljava/lang/Object;)Z
13: ifeq 28
16: aload_1
17: ldc #22 // String username
19: invokeinterface #30, 2 // InterfaceMethod javax/servlet/http/HttpServletRequest.getParameter:(Ljava/lang/String;)Ljava/lang/String;
24: astore_2
25: goto 31
28: ldc #34 // String UNKNOWN
30: astore_2
31: getstatic #36 // Field java/lang/System.out:Ljava/io/PrintStream;
34: aload_2
35: invokevirtual #42 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: return
LineNumberTable:
line 10: 0
line 12: 16
line 13: 25
line 16: 28
line 18: 31
line 19: 38
LocalVariableTable:
Start Length Slot Name Signature
0 39 0 this Lcom/test/TestASMIns;
0 39 1 request Ljavax/servlet/http/HttpServletRequest;
25 3 2 userName Ljava/lang/String;
31 8 2 userName Ljava/lang/String;
StackMapTable: number_of_entries = 2
frame_type = 28 /* same */
frame_type = 252 /* append */
offset_delta = 2
locals = [ class java/lang/String ]
}
13
существует условный переходifeq
к местоположению28
, который будет выполнен, еслиcontainsKey
вернетfalse
. Если это будет сделано, дляuserName
еще не будет допустимого значения. Инструкции28: ldc #34; 30: astore_2
хранят в себе константную строку"UNKNOWN"
, поэтому после завершения инструкцииastore_2
будет допустимое значение. Следовательно, для диапазона[28 - 30]
переменная не имеет допустимого значения. Но это не имеет отношения к используемой памяти, так как слот номер 2 будет зарезервирован на протяжении всего выполнения метода независимо от того, содержит он допустимое значение или нет. - person Holger   schedule 05.09.2017