Java 使用注释处理在内存中编译和加载类时出错
我正在使用Java 使用注释处理在内存中编译和加载类时出错,java,annotation-processing,java-compiler-api,Java,Annotation Processing,Java Compiler Api,我正在使用JavaCompiler在内存中编译和加载类 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaCompiler.CompilationTask compile = compiler.getTask(null, inMemoryFileManager, diagnostics, null, annotationClasses, compilationUnits); if (!compile.call())
JavaCompiler
在内存中编译和加载类
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaCompiler.CompilationTask compile = compiler.getTask(null, inMemoryFileManager, diagnostics, null, annotationClasses, compilationUnits);
if (!compile.call()) {
diagnostics.getDiagnostics().forEach(System.err::println);
}
我使用的是与中类似的Filemanager
和SimpleJavaObject
。我稍微修改了它,以便能够处理多个文件。如果你需要我的源代码,请让我知道
只要annotationClasses
为空,上述代码就可以正常运行。
但是,当我尝试将类添加到注释处理时,出现以下错误:
Class names, '<classNames>', are only accepted if annotation processing is explicitly requested
只有在明确请求注释处理时才接受类名称“”
对于类名,我尝试了Main、Main.java、package.Main和package.Main.java。它们都会导致相同的错误
我知道这是一个非常具体的场景。有没有人尝试过做类似的事情,可以帮助我
编辑:
/* Container for a Java compilation unit (ie Java source) in memory. */
private static class CompilationUnit extends SimpleJavaFileObject {
private final String source;
public CompilationUnit(String className, String source) {
super(URI.create("file:///" + className.replaceAll("\\.", "/") + ".java"), Kind.SOURCE);
this.source = source;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
@Override
public OutputStream openOutputStream() {
throw new IllegalStateException();
}
@Override
public InputStream openInputStream() {
return new ByteArrayInputStream(source.getBytes());
}
}
/* Container for Java byte code in memory. */
private static class ByteJavaFileObject extends SimpleJavaFileObject {
private ByteArrayOutputStream byteArrayOutputStream;
public ByteJavaFileObject(String className) {
super(URI.create("byte:///" + className.replaceAll("\\.", "/") + ".class"), Kind.CLASS);
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return null;
}
@Override
public OutputStream openOutputStream() {
byteArrayOutputStream = new ByteArrayOutputStream();
return byteArrayOutputStream;
}
@Override
public InputStream openInputStream() {
return null;
}
public byte[] getByteCode() {
return byteArrayOutputStream.toByteArray();
}
}
private static class InMemoryFileManager extends ForwardingJavaFileManager {
private final InMemoryClassLoader inMemoryClassLoader;
public InMemoryFileManager(JavaCompiler compiler, Map<String, ByteJavaFileObject> fileObjects) {
super(compiler.getStandardFileManager(null, null, null));
inMemoryClassLoader = new InMemoryClassLoader(fileObjects);
}
@Override
public JavaFileObject getJavaFileForOutput(Location notUsed, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
return inMemoryClassLoader.getFileObject(className);
}
@Override
public ClassLoader getClassLoader(Location location) {
return inMemoryClassLoader;
}
public InMemoryClassLoader getClassLoader() {
return inMemoryClassLoader;
}
}
private static class InMemoryClassLoader extends ClassLoader {
private final Map<String, ByteJavaFileObject> fileObjects;
public InMemoryClassLoader(Map<String, ByteJavaFileObject> fileObjects) {
this.fileObjects = fileObjects;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
ByteJavaFileObject fileObject = fileObjects.get(className);
return defineClass(className, fileObject.getByteCode(), 0, fileObject.getByteCode().length);
}
JavaFileObject getFileObject(String className) {
return fileObjects.get(className);
}
}
/*内存中Java编译单元(即Java源代码)的容器*/
私有静态类编译单元扩展SimpleJavaFileObject{
私有最终字符串源;
公共编译单元(字符串类名称、字符串源){
super(URI.create(“文件://“+className.replaceAll”(“\\\.”,“/”+“.java”)、Kind.SOURCE);
this.source=源;
}
@凌驾
public CharSequence getCharContent(布尔ignoreEncodingErrors){
返回源;
}
@凌驾
public OutputStream openOutputStream(){
抛出新的非法状态异常();
}
@凌驾
公共输入流openInputStream(){
返回新的ByteArrayInputStream(source.getBytes());
}
}
/*内存中Java字节码的容器*/
私有静态类ByteJavaFileObject扩展了SimpleJavaFileObject{
私有ByteArrayOutputStream ByteArrayOutputStream;
公共字节JavaFileObject(字符串类名称){
super(URI.create(“byte://“+className.replaceAll”(“\\.”,“/”+”.class”)、Kind.class);
}
@凌驾
public CharSequence getCharContent(布尔ignoreEncodingErrors){
返回null;
}
@凌驾
public OutputStream openOutputStream(){
byteArrayOutputStream=新建byteArrayOutputStream();
通过tearrayoutputstream返回;
}
@凌驾
公共输入流openInputStream(){
返回null;
}
公共字节[]getByteCode(){
返回byteArrayOutputStream.toByteArray();
}
}
MemoryFileManager中的私有静态类扩展了ForwardingJavaFileManager{
私有最终InMemoryClassLoader InMemoryClassLoader;
公共InMemoryFileManager(JavaCompiler编译器,映射文件对象){
super(compiler.getStandardFileManager(null,null,null));
inMemoryClassLoader=新的inMemoryClassLoader(文件对象);
}
@凌驾
公共JavaFileObject getJavaFileForOutput(位置未使用,字符串类名,JavaFileObject.Kind种类,FileObject同级)引发IOException{
返回inMemoryClassLoader.getFileObject(类名);
}
@凌驾
公共类加载器getClassLoader(位置){
在memoryclassloader中返回;
}
public InMemoryClassLoader getClassLoader(){
在memoryclassloader中返回;
}
}
MemoryClassLoader中的私有静态类扩展了ClassLoader{
私有最终映射文件对象;
公共InMemoryClassLoader(映射文件对象){
this.fileObjects=fileObjects;
}
@凌驾
受保护类findClass(字符串className)引发ClassNotFoundException{
ByteJavaFileObject fileObject=fileObjects.get(className);
返回defineClass(className,fileObject.getByteCode(),0,fileObject.getByteCode().length);
}
JavaFileObject getFileObject(字符串类名称){
返回fileObjects.get(className);
}
}
您尝试过package/Main.java吗?是的,它给出的类名无效。好的。你想完成什么?如果你能分享一些源代码,那会很有帮助。我正在尝试编译和加载带有注释处理的jpa类。如果我能在记忆中做到这一点,那就太好了。我将编辑我的问题以显示源代码。有意义。通过将AnnotationClass设置为null以外的值,您试图实现什么?我之所以问这个问题,只是因为在我使用这个api的几次中,我不相信我曾经为这个参数传递过任何信息。