2012-05-04 2 views
1

Я немного новичок в формате байт-кода Dalvik, я получаю, что означает этот регистр * -bearing, например. несущий объект, исключение и т. д.О * -регистрационных регистрах в байт-коде Dalvik

В то же время сгенерированный байт-код использует тип, а не регистры? Например,

throws Landroid/database/SQLException генерируется, но Landroid/database/SQLException представляет собой тип, то почему instruction summary говорит throw vAA, где vAA является регистром исключений подшипника? Я что-то упустил?

ответ

0

Это просто относится к типу данных, которые выполняет инструкция. Vm должен быть в состоянии определить статически, что регистр содержит этот тип данных в этой точке. Другими словами, для всех входящих кодов кода этот регистр был настроен на этот тип данных.

Если вы хотите изучить, как информация типа регистра распространяется более подробно, вы можете декомпилировать приложение с помощью baksmali с помощью параметра -r, который будет выводить комментарии до/после каждой инструкции с информацией о типах регистров для регистров которые имеют отношение к этой инструкции. Эта информация должна соответствовать информации типа регистра, которую vm создает внутри, в верификаторе байт-кода.

Например, у вас есть метод, который просто содержит:

const-string v0, "Hello World!" 
throw v0 

Это не будет разрешено, потому что в момент команды броска, регистр p0 не содержит ссылку на объект, который простирается от Throwable (т. е. не является «регистром, несущим исключение»).

Если вы используете -r в baksmali, вы увидите:

#v0=(Uninit); 
const-string v0, "Hello World!" 
#v0=(Reference,Ljava/lang/String;); 

#v0=(Reference,Ljava/lang/String;); 
throw v0 

который ясно показывает, что v0 не содержит исключение в пункте инструкции броска.

Кроме того, что-то вроде этого не будет позволено:

#v0=(Uninit); 
new-instance v0, Ljava/lang/Exception; 
#v0=(UninitRef,Ljava/lang/Exception;); 

#v0=(UninitRef,Ljava/lang/Exception;); 
invoke-direct {v0}, Ljava/lang/Exception;-><init>()V 
#v0=(Reference,Ljava/lang/Exception;); 

#p0=(Integer); 
if-eqz p0, :cond_9 

#v0=(Reference,Ljava/lang/Exception;); 
const-string v0, "Hello World!" 
#v0=(Reference,Ljava/lang/String;); 

:cond_9 
#v0=(Reference,Ljava/lang/Object;); 
throw v0 

Поскольку в точке вбрасывания, v0 может содержать либо исключение, или строку. В этом случае он сообщает «тип» v0 как Ljava/lang/Object;, потому что это общий родительский класс обоих типов.

+0

Спасибо за объяснение! Это помогло мне понять, что регистр * -bearing указывает тип регистра, а верификатор байт-кода в виртуальной машине будет обеспечивать согласованность типов. Однако, ваш второй пример - это байт-код, сгенерированный VM в исходной программе, который переназначает некоторую переменную исключения для строковой переменной? –

+0

Это просто произвольный пример, который я придумал, чтобы показать, что произойдет, если у вас есть 2 пути ввода кода, которые имеют разные типы регистров. – JesusFreke

Смежные вопросы