Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tool for java that uses annotation to monitor/log/report threads accessing given method?

Context:

I have created a small (java) multithread server for a game. Despite my best efforts of following the best practices it turned out that some methods that were intended to be called from just one thread got called from 2 or more threads. After debugging and analysis I have managed to "fix" my design but I was wondering:

The question:

Is there a tool (or if not - is it possible (and how) to be developed) that allows you to mark some methods with annotations like @SingleThread or @ThreadCount(2) or @ThreadNameLike("my_fancy_thread_group*") which counts/monitors/logs access to these methods like:

  • @SingleThread - checks if this method is always accessed by only thread
  • @ThreadCount(2) - is accessed by two threads exactly
  • @ThreadNameLike - is accessed only by threads with name matching the pattern(s)

The idea is to do a TEST run of the program and get at least log record that annotated condition is violated.

I was thinking that probably AspectJ can do the job to some extend with it's pointcuts but then I realized that some approach similar to Dagger / Dagger2 will be better, i.e. when you want to test your server you will have to turn on an annotation processor (let's called it hypothetically "SafetyFirst") which will generate adapter (wrapper?) classes which contain the monitoring code. Then you will run the server, run some load tests and then check the logs for violations (or in an ideal world - get a report file).

I fully realize that such tool:

  • will not provide 100% coverage of all potential cases;
  • will mask/trigger heisenbugs
  • will slow down the examined program

but at very least it can serve as an early warning system that will clearly advertise violations of the intended design.

like image 957
Ognyan Avatar asked May 26 '15 06:05

Ognyan


People also ask

How do I monitor JVM threads?

The simplest way to see the number of threads in Java is to use a graphical tool like Java VisualVM. Apart from the application threads, Java VisualVM also lists the GC or any other threads used by the application like JMX threads. Monitoring the number of threads is the most basic feature in Java VisualVM.

What is monitoring in Java?

Monitor in Java Concurrency is a synchronization mechanism that provides the fundamental requirements of multithreading namely mutual exclusion between various threads and cooperation among threads working at common tasks. Monitors basically 'monitor' the access control of shared resources and objects among threads.

When we start execution of Java application then JVM starts how many threads?

The JVM only starts 1 user thread, also called the "Main" thread.

How many threads can concurrently Java?

concurrent package is 16.


1 Answers

I used a similar test with AspectJ load time weaving for intended printing of all function calls within my package.

Best way of load time weaving is you dont dirty your classes like compile time wevaing. When you remove -javaagent:<path to aspectj lib> and your custom astpect lib classpath entry from your run command. Then all all gone, clear.

I made some changes and implemented a test covering @ThreadCount functionality you asked. You need to download and install AspectJ.

Please see code snippets:

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;
    }
}

Compiling: "C:/aspectj1.8/bin/ajc.bat" profile_ft.aj -cp C:/aspectj1.8/lib/aspectjrt.jar;../test/. -1.6 -outxml -outjar profile_ft.jar

Running: java -javaagent:C:/aspectj1.8/lib/aspectjweaver.jar -cp aspectj/profile_ft.jar;test test.Test1

like image 69
hsnkhrmn Avatar answered Sep 21 '22 13:09

hsnkhrmn