2222import javax .tools .JavaFileObject ;
2323import java .io .File ;
2424import java .io .IOException ;
25- import java .util .Collections ;
26- import java .util .Map ;
25+ import java .util .*;
2726import java .util .logging .Logger ;
2827
2928import static net .openhft .compiler .CompilerUtils .writeBytes ;
3029import static net .openhft .compiler .CompilerUtils .writeText ;
3130
3231@ SuppressWarnings ("StaticNonFinalField" )
3332public class CachedCompiler {
33+ private static final Map <ClassLoader , Map <String , Class >> loadedClassesMap = new WeakHashMap <ClassLoader , Map <String , Class >>();
34+
3435 @ Nullable
3536 private final File sourceDir ;
3637 @ Nullable
3738 private final File classDir ;
3839
40+ private final List <JavaFileObject > javaFileObjects = new ArrayList <JavaFileObject >();
41+
3942 public CachedCompiler (@ Nullable File sourceDir , @ Nullable File classDir ) {
4043 this .sourceDir = sourceDir ;
4144 this .classDir = classDir ;
@@ -62,26 +65,48 @@ Map<String, byte[]> compileFromJava(@NotNull String className, @NotNull String j
6265 writeText (file , javaCode );
6366 compilationUnits = CompilerUtils .s_standardJavaFileManager .getJavaFileObjects (file );
6467 } else {
65- compilationUnits = Collections .singletonList (new JavaSourceFromString (className , javaCode ));
68+ javaFileObjects .add (new JavaSourceFromString (className , javaCode ));
69+ compilationUnits = javaFileObjects ;
6670 }
6771 // reuse the same file manager to allow caching of jar files
6872 CompilerUtils .s_compiler .getTask (null , CompilerUtils .s_fileManager , null , null , null , compilationUnits ).call ();
6973 return CompilerUtils .s_fileManager .getAllBuffers ();
7074 }
7175
7276 public Class loadFromJava (@ NotNull ClassLoader classLoader , @ NotNull String className , @ NotNull String javaCode ) throws ClassNotFoundException {
77+ Class clazz = null ;
78+ Map <String , Class > loadedClasses ;
79+ synchronized (loadedClassesMap ) {
80+ loadedClasses = loadedClassesMap .get (classLoader );
81+ if (loadedClasses == null )
82+ loadedClassesMap .put (classLoader , loadedClasses = new LinkedHashMap <String , Class >());
83+ else
84+ clazz = loadedClasses .get (className );
85+ }
86+ if (clazz != null )
87+ return clazz ;
7388 for (Map .Entry <String , byte []> entry : compileFromJava (className , javaCode ).entrySet ()) {
7489 String className2 = entry .getKey ();
90+ synchronized (loadedClassesMap ) {
91+ if (loadedClasses .containsKey (className2 ))
92+ continue ;
93+ }
7594 byte [] bytes = entry .getValue ();
7695 if (classDir != null ) {
7796 String filename = className2 .replaceAll ("\\ ." , '\\' + File .separator ) + ".class" ;
7897 boolean changed = writeBytes (new File (classDir , filename ), bytes );
7998 if (changed )
8099 Logger .getLogger (CachedCompiler .class .getName ()).info ("Updated " + className2 + " in " + classDir );
81100 }
82- CompilerUtils .defineClass (classLoader , className2 , bytes );
101+ Class clazz2 = CompilerUtils .defineClass (classLoader , className2 , bytes );
102+ synchronized (loadedClassesMap ) {
103+ loadedClasses .put (className2 , clazz2 );
104+ }
105+ }
106+ // CompilerUtils.s_fileManager.clearBuffers();
107+ synchronized (loadedClassesMap ) {
108+ loadedClasses .put (className , clazz = classLoader .loadClass (className ));
83109 }
84- CompilerUtils .s_fileManager .clearBuffers ();
85- return classLoader .loadClass (className );
110+ return clazz ;
86111 }
87112}
0 commit comments