private void reloadSource( @NotNull ClassDescriptorSourceUnit sourceFile, boolean detectInnerClasses) { Class clasz = customClassLoader.loadClass(sourceFile, true); LinkedList<ClassDescriptorInner> innerClassDescList = sourceFile.getInnerClassDescriptors(); if (innerClassDescList != null && !innerClassDescList.isEmpty()) { for (ClassDescriptorInner innerClassDesc : innerClassDescList) { customClassLoader.loadClass(innerClassDesc, true); } } else if (detectInnerClasses) { // Aprovechando la carga de la clase, hacemos el esfuerzo de cargar todas las clases // dependientes lo más // posible clasz .getDeclaredClasses(); // Provoca que las inner clases miembro indirectamente se procesen // y carguen // a través del JProxyClassLoader de la clase padre clasz // Ahora bien, lo anterior NO sirve para las anonymous inner classes, afortunadamente en ese // caso podemos // conocer y cargar por fuerza bruta // http://stackoverflow.com/questions/1654889/java-reflection-how-can-i-retrieve-anonymous-inner-classes // ?rq=1 for (int i = 1; i < Integer.MAX_VALUE; i++) { String anonClassName = sourceFile.getClassName() + "$" + i; Class innerClasz = customClassLoader.loadInnerClass(sourceFile, anonClassName); if (innerClasz == null) { break; // No hay más o no hay ninguna (si i es 1) } } // ¿Qué es lo que queda por cargar pero que no podemos hacer explícitamente? // 1) Las clases privadas autónomas que fueron definidas en el mismo archivo que la clase // principal: no // las soportamos pues no podemos identificar en el ClassLoader que es una clase "hot // reloadable", no son // inner classes en el sentido estricto // 2) Las clases privadas "inner" locales, es decir no anónimas declaradas dentro de un // método, se // cargarán la primera vez que se usen, no podemos conocerlas a priori // porque siguen la notación className$NclassName ej. // JReloadExampleDocument$1AuxMemberInMethod. No // hay problema con que se carguen con un class loader antiguo pues // el ClassLoader de la clase padre contenedora será el encargado de cargarla en cuanto se // pase por el // método que la declara. } }
@Nullable public synchronized <T> Class<?> findClass(String className) { // Si ya está cargada la devuelve, y si no se cargó por ningún JProxyClassLoader se intenta // cargar por el // parent ClassLoader, por lo que siempre devolverá distinto de null si la clase está en el // classpath, que // debería ser lo normal try { return customClassLoader.findClass(className); } catch (ClassNotFoundException ex) { return null; } }