简体   繁体   中英

How to generate a unique hash code for a method instance?

I am doing some profiling with Aspectj.

I need to identify uniquely the instances of a method where the field been accessed For example:

public class Class{ int a; int b;
public void method1(){

  setA(5);
  setB(6); 

In this case with AspectJ I can obtain that an access to a and an access to b have been made by setA and SetB methods. And with

Thread.currentThread().getStackTrace();

I can know that setA and setB have been called by method1().

The name of the method is not enough I need also to univocally identify the instance of the method.

For example if method1 is called many times I have to discern that the access to a and access to b have been made by different instances of method1.

Any suggestion how can obtain the instance hashcode of a method excution?

A simple (untested, use at your own risk) solution that could possibly work would be to maintain a counter per method per thread:

private static final ConcurrentHashMap<String, ConcurrentHashMap<Long, AtomicInteger>>
    COUNTERS = new ConcurrentHashMap<>();

public static int getInvocationId(String methodName, long threadId) {
    return counter(methodName, threadId).getAndIncrement();
}

private static AtomicInteger counter(String methodName, long threadId) {
    ConcurrentHashMap<Long, AtomicInteger> map = countersForMethodName(methodName);
    AtomicInteger counter = map.get(threadId);
    if (counter == null) {
        AtomicInteger newCounter = new AtomicInteger();
        counter = map.putIfAbsent(threadId, newCounter);
        if (counter == null) {
            return newCounter;
        }
    }
    return counter;
}

private static ConcurrentHashMap<Long, AtomicInteger> countersForMethodName(
    String methodName) {
    ConcurrentHashMap<Long, AtomicInteger> map = COUNTERS.get(methodName);
    if (map == null) {
        ConcurrentHashMap<Long, AtomicInteger> newMap = new ConcurrentHashMap<>();
        map = COUNTERS.putIfAbsent(methodName, newMap);
        if (map == null) {
            return newMap;
        }
    }
    return map;
}

Then, in your advice, something like:

int invocationId = getInvocationId(thisJoinPoint.getSignature().getName(),
    Thread.currentThread().getId());
// do what you want with invocationId 

Note that this relies on the advice executing in the same thread as the target method—unfortunately, I'm not that familiar enough with AspectJ to know whether this assumption will always hold true.

CAVEAT: If your environment creates and expires new threads all the time, then the above tree will keep growing (essentially, a memory leak). If this is a problem, then you'll need to put in some other code to periodically enumerate all active threads, and prune the expired entries from the tree. In that case, you might want to use a map per-thread id, then per-method name to make pruning more efficient.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM