보통 bytecode instrumentation을 할 때 cglib, javassist등과 같은 도구를 사용하는 데 JVM 스펙상 이미 로드된 클래스코드에 대한 수정을 허용하지 않기 때문에(만약 조작한다 하더라도 그 코드는 의미가 없을 수 있다고 판단됩니다) javaagent의 premain을 이용하여 로드시점에 대상들에 대한 바이트 코드 조작이 필요합니다.
이 때 javassist를 사용하고 있는데 보통 WAS의 경우 다양한 클래스 로더(예 : EAR, Web, EJB 등)들을 가지고 있기 때문에 javassist에서 해당 클래스들에 대한 참조를 하지 못해 NotFoundException으로 인한 toClass등의 메소드에서 CannotCompileException이 발생합니다.
아래의 예제는 javaagent premain + ClassFileTransformer의 뼈대 코드로 WAS 클래스로더로 로딩되는 클래스를 참조할 수 있도록 합니다.
static 필드가 스택 메모리를 쓰는 것은 아닙니다. 스택메모리는 로컬 변수를 두는 데 사용합니다. 그러나 로컬 객체의 필드들도 스택에 저장될 지는 최종 기계어로 어떻게 최적화되고 번역되는지에 달려 있습니다. 하지만 이는 visibility 문제와는 전혀 관계가 없습니다.
만약 visibility 문제가 있다면 containsKey() 에서 보이지 않은 값이라면 iteration 에서도 안 보일 가능성이 있습니다. 따라서 그냥 ConcurrentHashMap 으로 바꾸는 것이 나을 것 같습니다.
한편, containsKey() 후에 반드시 remove() 가 온다면 그냥 remove() 를 바로 호출해서 리턴값의 null 여부를 검사하는 쪽이 더 안전할 것 같네요.
ThreadLocal을 이용하여 호출되는 비즈니스 메소드들의 순서를 추적할 때 사용할 수 있는 예제 코드입니다. 좀 중요한 것을 만들고 있는데 그것의 뼈대 코드라고 할 수 있습니다.
아주 단순한 예제라 그리 어렵지 않을 듯 합니다. ThreadLocal이란 것에 대해서는 구글링을 해보시면 많이 나올 겁니다. 이것과 Java instrumentation을 이용하면 bytecode레벨을 조작하여 성능에 별 영향없이 profiling tool을 만들 수 있습니다.