< prev index next > src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
Print this page
*/
package com.sun.tools.javac.main;
import java.io.*;
+ import java.lang.module.Configuration;
+ import java.lang.reflect.Method;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.InvalidPathException;
import java.nio.file.ReadOnlyFileSystemException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.MissingResourceException;
+ import java.util.Optional;
import java.util.Queue;
import java.util.ResourceBundle;
+ import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import javax.annotation.processing.Processor;
import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
import com.sun.tools.javac.util.Log.WriterKind;
import static com.sun.tools.javac.code.Kinds.Kind.*;
+ import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.resources.CompilerProperties.Notes;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
* containing this class.
* @param cdef The class definition from which code is generated.
*/
JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
try {
+ if (Feature.REFLECT_METHODS.allowedInSource(source)) {
+ Optional<CodeReflectionTransformer> reflectMethods = reflectMethods();
+ if (reflectMethods.isPresent()) {
+ reflectMethods.get().genCode(context, cdef);
+ }
+ }
+
if (gen.genClass(env, cdef) && (errorCount() == 0))
return writer.writeClass(cdef.sym);
} catch (ClassWriter.PoolOverflow ex) {
log.error(cdef.pos(), Errors.LimitPool);
} catch (ClassWriter.StringOverflow ex) {
return !shouldStop(CompileState.ATTR);
}
public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
modules.initModules(roots);
+
if (roots.isEmpty()) {
enterDone();
}
return roots;
}
}
if (shouldStop(CompileState.TRANSTYPES))
return;
+ if (Feature.REFLECT_METHODS.allowedInSource(source)) {
+ Optional<CodeReflectionTransformer> reflectMethods = reflectMethods();
+ if (reflectMethods.isPresent()) {
+ env.tree = reflectMethods.get().translateTopLevelClass(context, env.tree, localMake);
+ }
+ }
+
env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
compileStates.put(env, CompileState.TRANSTYPES);
if (shouldStop(CompileState.TRANSPATTERNS))
return;
log.useSource(prev);
}
}
+ Optional<CodeReflectionTransformer> reflectMethods() {
+ return CodeReflectionSupport.CODE_LAYER != null ?
+ ServiceLoader.load(CodeReflectionSupport.CODE_LAYER, CodeReflectionTransformer.class).findFirst() :
+ Optional.empty();
+ }
+
+ public static class CodeReflectionSupport {
+ public static final ModuleLayer CODE_LAYER;
+
+ static {
+ if (ModuleLayer.boot().findModule("jdk.incubator.code").isPresent()) {
+ // we are in an exploded build, so just use the boot layer
+ CODE_LAYER = ModuleLayer.boot();
+ } else if (java.lang.module.ModuleFinder.ofSystem().find("jdk.incubator.code").isPresent()) {
+ // The incubating jdk.incubator.code module is installed, but not in the boot layer
+ // The module needs to be resolved so the jdk.compiler module can find and use the service provider
+ // for CodeReflectionTransformer
+ ModuleLayer parent = ModuleLayer.boot();
+ // Create a new configuration from the boot layer configuration with the resolved jdk.incubator.code module
+ Configuration cf = parent.configuration()
+ .resolve(java.lang.module.ModuleFinder.of(), java.lang.module.ModuleFinder.ofSystem(), Set.of("jdk.incubator.code"));
+ ClassLoader scl = ClassLoader.getSystemClassLoader();
+ // Create the code module layer using the new configuration and the system class loader
+ CODE_LAYER = parent.defineModulesWithOneLoader(cf, scl);
+ Module codeReflectionModule = CODE_LAYER.findModule("jdk.incubator.code").get();
+ Module jdkCompilerModule = JavaCompiler.class.getModule();
+ // Add exports to all jdk.compiler packages so that the jdk.incubator.code module can use them
+ for (String packageName : jdkCompilerModule.getPackages()) {
+ jdkCompilerModule.addExports(packageName, codeReflectionModule);
+ }
+ // Add exports to all java.base packages so that the jdk.incubator.code module can use them
+ // We need to do so by calling a method in java.base reflectively
+ try {
+ Class<?> codeModuleLayerInit = Class.forName("jdk.internal.access.code.CodeModuleLayerInit");
+ Method initLayerMethod = codeModuleLayerInit.getDeclaredMethod("initCodeModuleLayer", ModuleLayer.class);
+ initLayerMethod.invoke(null, CODE_LAYER);
+ } catch (ReflectiveOperationException ex) {
+ throw new AssertionError(ex);
+ }
+ } else {
+ // If we run in bootstrap mode, there might be no jdk.incubator.code
+ CODE_LAYER = null;
+ }
+ }
+ }
+
/** Generates the source or class file for a list of classes.
* The decision to generate a source file or a class file is
* based upon the compiler's options.
* Generation stops if an error occurs while writing files.
*/
< prev index next >