2009-06-15 16 views
4

J'aimerais connaître la taille d'un tableau alloué en regardant le bytecode, si cette information est connue au moment de la compilation, bien sûr. Contexte: Je souhaite écrire un détecteur FindBugs (qui examine le bytecode compilé) et signaler certaines occurrences d'allocations de matrices. Afin de filtrer les faux positifs, je ne suis pas intéressé par les "petits" tableaux, mais uniquement ceux dont la taille n'est pas disponible au moment de la compilation ou qui sont plus grands qu'un seuil configurable. Étant donné que le code source FindBugs n'est pas trop documenté, je cherche des indications sur la façon de commencer - peut-être y a-t-il déjà un dectector qui fasse quelque chose de similaire que je pourrais regarder.Comment détecter la taille d'un tableau dans un bytecode Java (FindBugs)

Répondre

2

Cela pourrait obtenir une sorte de délicate. Mes connaissances sont incomplètes, mais vous aurez au moins trois types d'instructions à surveiller (NEWARRAY, ANEWARRAY et MULTIANEWARRAY). En regardant l'instruction précédente (ou dans le cas de MULTIANEWARRAY, n instructions précédentes) obtient la taille, qui même si elle était une constante pourrait être chargé avec BIPUSH, SIPUSH ou LDC (autre chose?) Selon la taille. Comme vous l'avez noté, si la classe est le résultat d'un calcul, il se peut que vous retraciez des instructions indéfiniment. Si je me souviens bien, FindBugs utilise le BCEL en interne, mais je n'ai jamais cherché à savoir exactement à quel point ils sont intelligents. Si l'une ou l'autre de ces équipes a des listes de diffusion appropriées, elles peuvent s'avérer un meilleur endroit à demander - elles sauront probablement au moins si quelqu'un a déjà fait ce chemin.

5

Eh bien, s'ils sont alloués en fonction d'une constante, vous pouvez vérifier une constante qui a été poussée juste avant l'allocation. Par exemple:

class ArraySize { 
    private static final int smallsize = 10; 
    private static final int largesize = 1000; 
    public static void main(String[] args) { 
     int[] small = new int[smallsize]; 
     int[] big = new int[largesize]; 
    } 
} 

donne le bytecode:

Compiled from "ArraySize.java" 
class ArraySize extends java.lang.Object{ 
ArraySize(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: bipush 10 
    2: newarray int 
    4: astore_1 
    5: sipush 1000 
    8: newarray int 
    10: astore_2 
    11: return 

} 
+0

Merci, c'est déjà un début. Dans votre exemple, il va intégrer les constantes. Il devient plus difficile quand vous avez des choses comme int x = 10; nouvel octet [5 + x]; Même si 15 est le résultat évident, en fonction du compilateur (et de ses paramètres), il se peut que le calcul soit effectué sur la pile juste avant la nouvelle allocation. J'aimerais savoir s'il existe un moyen standard d'y parvenir dans FindBugs. –

+0

Je ne connais pas l'intérieur de FindBugs, désolé; tout ce que je sais c'est un peu de bytecode. –