есть ли хэш-код / ​​адрес кучи для примитивных типов в Java? - PullRequest
0 голосов
/ 25 февраля 2011

Я пытался найти какое-то приближение для адресации в куче, и вы, ребята, дали мне функцию System.IdentityHashCode(Object).

Проблема в том, что эта функция не подходит для примитивных типов.Я объясню, почему.

Мне дают в качестве входного файла скомпилированной программы Java - класс.Моя цель состоит в том, чтобы построить несколько графиков, которые будут содержать некоторую информацию о доступе к переменным во времени.Я понятия не имею, как код выглядит заранее, и моя тактика - это инструментарий моего собственного байт-кода для каждой инструкции LOAD и STORE.Я использую инструментарий ASM Java Bytecode.

Поэтому я не могу сделать что-то вроде:

identityHashCode(Integer.valueOf(...))

, потому что у меня нет указания, является ли тип int, double, long и т. Д..

Я хочу иметь возможность определять между различными экземплярами одного и того же класса:

Например:

class foo {
int a;
}
foo b;
foo c;
b.a++;
c.a++;

Но когда дело доходит до байт-кода, нетсвязь между именем "b" / "c" и атрибутом a.Все, что я "вижу", - это то, что увеличивается.Оба расценены как!если бы это было Object a, я мог бы использовать System.identityHashCode (), чтобы различать их.Но я не могу.

Чтобы прояснить ситуацию, посмотрите на следующий пример:

package manipulate;

public class Test {
        int c;
        public static void main(String[] args) {
            Test a=new Test();
            Test b=new Test();
            a.c++;
            b.c++;
        }
    }

, который будет переведен (основная функция) в следующий байт-код:

   L0
    LINENUMBER 7 L0
    NEW manipulate/Test
    DUP
    INVOKESPECIAL manipulate/Test.<init>()V
    ASTORE 1
   L1
    LINENUMBER 8 L1
    NEW manipulate/Test
    DUP
    INVOKESPECIAL manipulate/Test.<init>()V
    ASTORE 2
   L2
    LINENUMBER 9 L2
    ALOAD 1
    DUP
    GETFIELD manipulate/Test.c : I
    ICONST_1
    IADD
    PUTFIELD manipulate/Test.c : I
   L3
    LINENUMBER 10 L3
    ALOAD 2
    DUP
    GETFIELD manipulate/Test.c : I
    ICONST_1
    IADD
    PUTFIELD manipulate/Test.c : I
   L4
    LINENUMBER 11 L4
    RETURN

И, как вы можете видеть, в стеке есть только значение целого числа c.Поэтому, учитывая этот код, я не могу определить между этими двумя буквами!

Ответы [ 4 ]

3 голосов
/ 25 февраля 2011

Примитивы не имеют тождеств.Они сравниваются по значению, а не по ссылке.Адрес в памяти примитива в локальной переменной, вероятно, находится в регистре или в стеке, а расположение примитивного члена массива или объекта связано с адресом кучи его родителя.

Java не предоставляет никаких стандартизированных средств доступа к памяти, и альтернативы, такие как System.identityHashCode, не распространяются на них.

Вызов System.identityHashCode с примитивом вызовет ложный бокс, который даст бессмысленные результаты.

Если вам действительно нужно знать местоположение примитивного члена, вы можете написать код C с привязками JNI, чтобы получить дескриптор объекта Java, получить указатель и преобразовать его в целочисленный тип Java типаправильная ширина, но вам лучше всего найти другой способ сделать то, что вы пытаетесь сделать.

Еще один вариант - использовать существующие ловушки Java-отладчика: http://download.oracle.com/javase/6/docs/technotes/guides/jpda/architecture.html#jdi

1 голос
/ 25 февраля 2011

У меня есть байт-код Java.У меня нет b или c, и я не знаю о них.У меня есть только значение в стеке

Если в стеке есть локальные переменные, они имеют номера переменных.Эти числа являются локальными для фрейма стека, в котором выполняется метод, и две переменные одинаковы, если имеют одинаковое число.

Если в вашей оценке есть два примитивных значения (аргумент / операнд / результат), они одинаковы (в том же смысле, что и для переменных), если они существуют в одно и то же время с одним и тем же индексом стека.


В вашем примере вы видите, что две GETFIELD manipulate/Test.c : I инструкцииоперируйте каждым с текущим значением в стеке (которое помещается туда ALOAD 1 или ALOAD 2).Это текущее значение является объектом, к которому принадлежит ваша переменная, поэтому вы можете вставить туда свой счетный код для этого объекта (сначала выполните DUP).

0 голосов
/ 25 февраля 2011

Когда вы спросили об адресах памяти и получили ответ на identityhashCode, ключевой фразой было «некоторое приближение». Нет гарантии, что это значение будет адресом памяти, и даже самое агрессивное утверждение состоит в том, что это отображение из адреса в целое число. Вы абсолютно не можете надежно определить адрес объекта в Java и даже не должны думать о попытках использовать примитивы. Во-первых, нет никакой гарантии, что компилятор не будет их перемещать. Нет даже гарантии, что переменная когда-либо имеет адрес.

Если вы хотите определить, являются ли два объекта одинаковыми, вы можете использовать "==". Вопрос даже не имеет смысла с примитивами, и вы не должны делать это.

0 голосов
/ 25 февраля 2011

Я не уверен, что понимаю вопрос, вы хотите знать, действительно ли ba влияет на ту же переменную, что и ca?

В вашем случае ba будет таким же, как ca, если b == c.Если вы объявляете static, он будет использоваться всеми экземплярами foo.

...