Почему этот простой байт-код Java вызывает ошибку StackOverflow? - PullRequest
1 голос
/ 19 января 2011

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

После того, как я думал, что для этого было сделано простое изменение байт-кода, я получаю StackOverflowError прямо перед выполнением метода-оболочки, даже если стек в основном пуст.Вот мой тестовый класс:

public class SimpleTest {
    public static void main(String[] args) throws IOException {
        Perf.getPerf().highResCounter();
    }
}

Обычно эта программа ничего не выдаёт на консоли.Однако мой инструментированный байт-код выполняет println () перед выполнением нативного метода $ wrapper $ highResCounter ().Это можно увидеть в соответствующем байт-коде класса Perf после инструментирования:

public long highResCounter() {
    getstatic PrintStream System.out
    ldc String Constant "this is an instrumented println"
    invokevirtual void PrintStream.println(String)
    aload 0
    invokevirtual long Perf.$wrapped$highResCounter()
    lreturn
}

public native long $wrapped$highResCounter();

Я новичок в байт-коде Java, поэтому я, вероятно, допустил здесь ошибку.Вот выходные данные программы, которые показывают, что println () выполняется, но где-то после первого invokevirtual вызова StackOverflowError:

this is an instrumented println call
Exception in thread "main" java.lang.StackOverflowError
   at com.foo.SimpleTest.main(SimpleTest.java:17)

Что может быть причиной этого StackOverflowError?И как мне это исправить?

Ответы [ 3 ]

1 голос
/ 27 января 2011

В опубликованном коде нет ошибок.Проблема была вызвана недопустимыми значениями атрибутов метода MAX_STACK и MAX_LOCALS, которые обычно рассчитываются компилятором.

Используемая мной библиотека байт-кода, ASM, дает вам возможность автоматически рассчитать эти значения,и я не воспользовался этим.Изменяя конструктор ASM ClassWriter на следующий, я получаю безошибочный код:

int flags = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS;
ClassWriter writer = new ClassWriter(flags);

[1] http://asm.ow2.org/asm33/javadoc/user/org/objectweb/asm/ClassWriter.html#COMPUTE_FRAMES

1 голос
/ 19 января 2011

Ваш метод highResCounter вызывает сам себя:

public long highResCounter() {
    [...]
    invokevirtual long Perf.$wrapped$highResCounter()

У вас есть еще код, который вы можете показать нам, чтобы узнать почему?

0 голосов
/ 23 января 2011

показать нативную функцию, это также может быть проблемой само по себе.iirc StackOverFlowError перехватывается, поэтому даже код JNI C может вызвать его.

...