/** Obtain a (cached) ClassReader for the given class. */
 private ClassReader getClassReader(Class clazz) throws IOException {
   ClassReader classReader = (ClassReader) this.classReaderCache.get(clazz);
   if (classReader != null) return classReader;
   synchronized (this.classReaderCache) {
     classReader = (ClassReader) this.classReaderCache.get(clazz);
     if (classReader != null) return classReader;
     InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz));
     if (is == null) {
       throw new FileNotFoundException("Class file for class [" + clazz.getName() + "] not found");
     }
     try {
       classReader = new ClassReader(is);
       this.classReaderCache.put(clazz, classReader);
     } finally {
       is.close();
     }
     return classReader;
   }
 }