Подтвердить что ты не робот

Инструмент для java, который использует аннотацию для мониторинга/журнала/потока отчетов, обращаясь к данному методу?

Контекст:

Я создал небольшой (java) многопоточный сервер для игры. Несмотря на мои лучшие усилия, следуя лучшим практикам, выяснилось, что некоторые методы, которые должны были быть вызваны только из одного потока, вызывались из двух или более потоков. После отладки и анализа мне удалось "исправить" мой дизайн, но мне было интересно:

Вопрос:

Есть ли инструмент (или если нет - возможно ли это (и как)), чтобы вы могли отметить некоторые методы с аннотациями типа @SingleThread или @ThreadCount(2) или @ThreadNameLike("my_fancy_thread_group*"), которые подсчитывают/контролируют/регистрируют доступ к этим методам, например:

  • @SingleThread - проверяет, доступен ли этому методу только поток
  • @ThreadCount(2) - достигается двумя потоками точно
  • @ThreadNameLike - доступен только потоками с именем, соответствующим шаблону (-ам)

Идея состоит в том, чтобы выполнить прогон TEST программы и получить хотя бы запись журнала, которая нарушает аннотированное условие.

Я думал, что, возможно, AspectJ может выполнить эту работу до некоторой степени с помощью pointcut, но потом я понял, что какой-то подход, подобный Dagger/Dagger2, будет лучше, т.е. когда вы хотите протестировать свой сервер, вам придется включить обработчик аннотации (предположительно называемый гипотетически "SafetyFirst" ), который будет генерировать классы адаптера (оболочки), которые содержат код мониторинга. Затем вы запустите сервер, запустите несколько нагрузочных тестов, а затем проверьте журналы на наличие нарушений (или в идеальном мире - получите файл отчета).

Я полностью понимаю, что такой инструмент:

  • не будет обеспечивать 100% охвата всех потенциальных случаев;
  • будет маскировать/запускать heisenbugs
  • замедлит рассмотренную программу

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

4b9b3361

Ответ 1

Я использовал аналогичный тест с тканью времени AspectJ для предполагаемой печати всех вызовов функций в моем пакете.

Лучший способ ткать время загрузки - вы не загрязняете свои классы, как компиляция времени. Когда вы удаляете -javaagent:<path to aspectj lib> и свой пользовательский атрибут astpath lib classpath из команды запуска. Тогда все прошло, ясно.

Я внесла некоторые изменения и внедрил тестовое покрытие, которое вы задали в функции @ThreadCount. Вам необходимо загрузить и установить AspectJ.

См. фрагменты кода:

aspect Profile {

    private static Map<String, AtomicInteger> counterMap = new HashMap<String, AtomicInteger>();

    pointcut threadCountPc(test.ThreadCount tc) : execution(* test..*(..)) && @annotation(tc);

    Object around(test.ThreadCount tc) : threadCountPc(tc) {        

        String signature = thisJoinPointStaticPart.getSignature().toString();

        AtomicInteger counter = getCounter(signature);
        int currentValue = counter.incrementAndGet();

        if (currentValue >= tc.value()){
            System.out.println("[Thread Name:" + Thread.currentThread().getName() + 
            "] Method Name:" + signature + ", threadCount:" + currentValue + " exceeds " + tc.value());
        }

        try{
            return proceed(tc);
        }finally{
            counter.decrementAndGet();          
        }
    }

    private static AtomicInteger getCounter(String methodName){
        AtomicInteger value = counterMap.get(methodName);
        if (value == null){
            synchronized (counterMap){
                value = counterMap.get(methodName);
                if (value == null){
                    value = new AtomicInteger(0);
                    counterMap.put(methodName, value);
                }
            }
        }
        return value;
    }
}

Компиляция: "C:/aspectj1.8/bin/ajc.bat" profile_ft.aj -cp C:/aspectj1.8/lib/aspectjrt.jar;../test/. -1.6 -outxml -outjar profile_ft.jar

Запуск: java -javaagent:C:/aspectj1.8/lib/aspectjweaver.jar -cp aspectj/profile_ft.jar;test test.Test1