Je dois instrumenter des méthodes natives pour effectuer un appel statique simple avant de l'exécuter normalement. Parce que les méthodes sont natives, je dois utiliser le "setNativePrefix" feature et envelopper les méthodes natives avec un appel intermédiaire avec la signature de la méthode d'origine. Après ce que je pensais être un simple changement de bytecode pour accomplir ceci, j'obtiens un StackOverflowError juste avant que la méthode wrapper soit exécutée même si la pile est fondamentalement vide. Voici ma classe de test:Pourquoi ce simple bytecode Java provoque-t-il une erreur StackOverflow?
public class SimpleTest {
public static void main(String[] args) throws IOException {
Perf.getPerf().highResCounter();
}
}
Normalement, ce programme ne produira rien sur la console. Cependant, mon bytecode instrumenté exécute un println() avant d'exécuter la méthode native $ wrapper $ highResCounter(). Cela peut être vu dans la catégorie concernée après l'instrumentation bytecode 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();
Je suis un peu nouveau pour bytecode Java, donc je probablement fait une erreur. Voici la sortie du programme, ce qui montre que le println() est exécuté, mais quelque part après la première invokevirtual appel a StackOverflowError:
this is an instrumented println call
Exception in thread "main" java.lang.StackOverflowError
at com.foo.SimpleTest.main(SimpleTest.java:17)
ce qui pourrait causer ce StackOverflowError? Et comment puis-je le réparer?
Avez-vous le SimpleTest.java complet pour nous? Avez-vous traversé avec un débogueur? Peut-être que vous ne courez pas ce que vous pensez que vous exécutez. (Cela me rappelle un bug il ya des années, j'ai cherché pendant des heures jusqu'à ce que je me rende compte que mon classpath pointait vers d'anciens fichiers de classe :) –
C'est l'intégralité de la classe, moins la déclaration d'import et l'identifiant du paquet. Aucun initialiseur statique ou quoi que ce soit. – nahsra
Cela arrive aussi sur n'importe quelle méthode native: comme StrictMath.sin(). Je ne pense pas que cela ait quelque chose à voir avec Perf. – nahsra