Как проверить длину байт-кода метода Java

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

Я нашел ручной способ, например, такой: сколько байтов байт-кода имеет определенный метод в Java? Однако моя цель - сканировать многие файлы автоматически.

Я пытался использовать jboss-javassist, но AFAIK получение длины байт-кода доступно только на уровне класса.

1 ответ

Решение

Огромные методы могут действительно никогда не быть встроенными, но у меня есть сомнения относительно порогового значения 8000. Этот комментарий предлагает гораздо меньший предел, хотя в любом случае он зависит от платформы и конфигурации.

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

try(InputStream is=javax.swing.JComponent.class.getResourceAsStream("JComponent.class")) {
    ClassFile​ cf = new ClassFile(new DataInputStream(is));
    for(MethodInfo mi: cf.getMethods()) {
        CodeAttribute ca = mi.getCodeAttribute();
        if(ca == null) continue; // abstract or native
        int bLen = ca.getCode().length;
        if(bLen > 300)
            System.out.println(mi.getName()+" "+mi.getDescriptor()+", "+bLen+" bytes");
    }
}

Это было написано и протестировано с последней версией Javassist, которая использует Generics в API. Если у вас другая / старая версия, вы должны использовать

try(InputStream is=javax.swing.JComponent.class.getResourceAsStream("JComponent.class")) {
    ClassFile​ cf = new ClassFile(new DataInputStream(is));
    for(Object miO: cf.getMethods()) {
        MethodInfo mi = (MethodInfo)miO;
        CodeAttribute ca = mi.getCodeAttribute();
        if(ca == null) continue; // abstract or native
        int bLen = ca.getCode().length;
        if(bLen > 300)
            System.out.println(mi.getName()+" "+mi.getDescriptor()+", "+bLen+" bytes");
    }
}
Другие вопросы по тегам