2015-08-17 8 views
0

Я скомпилировал плагин .jar с файлом X.class. Файл X.class содержит метод Y с параметрами Y (строка s1, строка s2 ....). Мне нужно перейти к еще одной строке - поэтому я запустил reJ и dirtyJoe, отредактировал дескриптор моего метода Y, изменил максимальное количество локальных переменных с 8 на 9, добавил новую локальную переменную, установил ее так же, как и предыдущие, просто дал ей другую индекс, отредактированный код и сохраненный метод. Я упаковал его обратно в .jar-файл и попытался скомпилировать в Unity новую версию моего плагина. К сожалению, - он дал мне ошибку говоря моя новая переменная недействительна -Добавление параметра для работы в Java Байткод

EXCEPTION FROM SIMULATION: 
local 0008: invalid 

...at bytecode offset 00000036 
locals[0000]: Ljava/lang/String; 
locals[0001]: Ljava/lang/String; 
locals[0002]: Ljava/lang/String; 
locals[0003]: Ljava/lang/String; 
locals[0004]: Ljava/lang/String; 
locals[0005]: [B 
locals[0006]: Landroid/net/Uri; 
locals[0007]: Landroid/content/Intent; 
locals[0008]: <invalid> 
stack[0001]: Landroid/content/Intent; 
stack[top0]: string{"android.intent.extra.TEXT"} 
...while working on block 0036 
...while working on method StartShareIntentMedia:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V 
...while processing StartShareIntentMedia (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V 
...while processing com/androidnative/features/social/common/SocialGate.class 

Это мой самый первый раз с Java байткод, надеюсь, я буду получить некоторую помощь. Благодаря!

+0

Я немного смущен, почему вы пытаетесь установить параметр на уровне байт-кода - не могли бы вы объяснить, почему использование функции в качестве опции не соответствует вашим потребностям? – romeara

+0

, потому что мне нужно поставить еще одну строку в андроид Intent, вызванный в этой функции. –

ответ

2

Редактирование байт-кода не для слабонервных. Прежде чем начать, я рекомендую прочитать спецификацию JVM.

Это, как говорится, есть пара вещей, которые вы можете делать неправильно, основываясь на вашем описании.

В начале метода параметры метода передаются в локальных слотах переменной 0 .. n-1. Вы не можете просто выбрать какой-либо индекс для своей новой локальной переменной, вам нужно использовать индекс после последнего текущего параметра. Если байт-код уже использует этот слот для чего-то другого, вам придется настроить все его использование на что-то еще. В качестве альтернативы вы можете добавить последовательность перемещения (то есть aload nastore y) в начале способа. Это не повлияет на использование этого слота в качестве локальной переменной позже в методе.

Если у вас есть отладочная информация, например LocalVariableTable, вам нужно будет отрегулировать все ссылки в этом. Если байт-код имеет номер StackMapTable, вам придется его настроить. Предполагая, что код не использует invokedynamic, вероятно, проще просто изменить версию байт-кода обратно на 50.0 и полностью удалить таблицу сопоставлений стека.

Далее, вам придется изменить дескриптор метода. Дескриптор по существу дает подпись метода, а в байт-коде методы всегда идентифицируются тройкой (класс, имя, дескриптор). Вам нужно будет добавить строку в качестве параметра в конце дескриптора перед окончательным закрывающим скобкой и типом возврата. Вам придется добавить новый дескриптор в постоянный пул, если его еще нет.

Затем вам нужно будет отрегулировать определение метода для ссылки на новый дескриптор, а также отрегулировать каждое место, где вызывается этот метод (лучше надеяться, что наследование и отражение не будут задействованы!).

И, конечно же, вам также придется настраивать каждый callsite, чтобы фактически передать новый параметр.

+0

Спасибо за отличный ответ! Мне больше не нужна функция, над которой я работал, но я все равно попытаюсь добиться этого в свободное время;) –

+0

'StackMapTable' был добавлен в версии 50, поэтому вам придется перейти к версии * до 50 * при удалении 'StackMapTable's. Помимо 'invokedynamic', вы потеряете все функции J8,' static' и 'default' методы в' interface ', типа аннотации и параметры отражающего метода, а также ... – Holger

+0

@Holger Legacy проверка fallback является необязательной в версии 50. Итак если вы хотите быть педантичной и гарантированной поддержкой, вам нужно будет вернуться к 49, но любая JVM, о которой вы заботитесь, вернется к проверке устаревшей версии 50, если нет комбинации стека. – Antimony