Поиск ошибочного вывода в System.out в большой программе Java - PullRequest
3 голосов
/ 21 апреля 2010

У нас есть большая база Java-кода [~ 1 M строк].

В базе кода (где-то) скрыт какой-то старый отладочный вывод в System.out, который мы хотим удалить (его беспорядок).

Проблема в том, что исходная база кода настолько велика, что мы не можем легко определить, откуда поступает вывод. Нам нужен способ увидеть, откуда вызывается System.out.println (например, трассировка стека из исключения или чего-то подобного).

Он не подходит для отладки - ошибочный вывод исходит из какого-то ошибочного потока где-то и т. Д.

Есть идеи, как отследить источник этого ошибочного вывода?

PS: 99,99% вызовов System.out являются законными, и у нас их тысячи, поэтому простой поиск в базе кода для вызовов System.out не является решением!

Ответы [ 2 ]

7 голосов
/ 21 апреля 2010

Существует метод System.setOut(). Если вы действительно в отчаянии, установите это для какой-нибудь обертки реального стандартного вывода и сделайте все, что у вас есть. Например. сравните записанную строку с чем-то и сгенерируйте, если это ошибочный вывод.

2 голосов
/ 21 апреля 2010

С AspectJ вы можете легко распечатать подпись для класса, который вызывает System.out.

Ниже приведен простой пример, который будет рекомендован TraceAspect. Важной частью является то, что класс находится в демонстрационном пакете и вызывает System.out. Этот аспект также будет рекомендовать все вызовы System.out из всех классов в подпакете любой глубины демонстрационного пакета.

package demo;

public class DemoClass {

    public void demo() {
        System.out.println("inside demo method..");
    }

    public static void main(String[] args) {
        new DemoClass().demo();
    }
}

Чтобы распечатать пакет и имя класса до вызова System.out, вы можете добавить Aspect следующим образом:

@Aspect
public class TraceAspect {

    @Pointcut("call(* java.io.PrintStream.*(..))")
    public void sysoutPointcut() {
    }

    @Pointcut("within(demo..*)")
    public void packagePointcut() {
    }

    @Before("sysoutPointcut() && packagePointcut()")
public void beforeSysoutCallInsideDemoPackage(JoinPoint joinPoint) {
    System.out.print(joinPoint.getThis().getClass().getName() + ":"
            + joinPoint.getSourceLocation().getLine() + " - ");
}
}

Результат выполнения метода main в DemoClass:

demo.DemoClass:6 - inside demo method..

Используя Eclipse и плагин AspectJ, вы можете щелкнуть правой кнопкой мыши свой проект и выбрать Configure -> Convert to AspectJ project. Тогда код выше будет работать.

Я написал больше об AspectJ в стиле @AspectJ здесь .

...