Java 警告:文件类型为';[在此插入类]';在上一轮中创建的将不接受注释处理

Java 警告:文件类型为';[在此插入类]';在上一轮中创建的将不接受注释处理,java,java-7,Java,Java 7,我将现有的代码库切换到Java 7,并不断收到以下警告: warning: File for type '[Insert class here]' created in the last round will not be subject to annotation processing. 快速搜索显示没有人点击此警告 javac编译器源代码中也没有记录: 来自OpenJDK\langtools\src\share\classes\com\sun\tools\javac\processi

我将现有的代码库切换到Java 7,并不断收到以下警告:

warning: File for type '[Insert class here]' created in the last round 
  will not be subject to annotation processing.
快速搜索显示没有人点击此警告

javac编译器源代码中也没有记录:

来自OpenJDK\langtools\src\share\classes\com\sun\tools\javac\processing\JavacFiler.java

private JavaFileObject createSourceOrClassFile(boolean isSourceFile, String name) throws IOException {
    checkNameAndExistence(name, isSourceFile);
    Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT);
    JavaFileObject.Kind kind = (isSourceFile ?
                                JavaFileObject.Kind.SOURCE :
                                JavaFileObject.Kind.CLASS);

    JavaFileObject fileObject =
        fileManager.getJavaFileForOutput(loc, name, kind, null);
    checkFileReopening(fileObject, true);

    if (lastRound) // <-------------------------------TRIGGERS WARNING
        log.warning("proc.file.create.last.round", name);

    if (isSourceFile)
        aggregateGeneratedSourceNames.add(name);
    else
        aggregateGeneratedClassNames.add(name);
    openTypeNames.add(name);

    return new FilerOutputJavaFileObject(name, fileObject);
}
private JavaFileObject createSourceOrClassFile(布尔isSourceFile,字符串名)引发IOException{
CheckName和Existence(名称,isSourceFile);
位置loc=(isSourceFile?源输出:类输出);
JavaFileObject.Kind种类=(isSourceFile?
JavaFileObject.Kind.SOURCE:
JavaFileObject.Kind.CLASS);
JavaFileObject文件对象=
getJavaFileForOutput(loc、name、kind、null);
CheckFileResopening(fileObject,true);

如果(lastRound)/我仔细查看了java 7编译器选项,发现了以下内容:

-隐式:{class,none} 控制隐式加载的源文件的类文件的生成。若要自动生成类文件,请使用-implicit:class。若要禁止生成类文件,请使用-implicit:none。如果未指定此选项,默认值为自动生成类文件。在这种情况下,如果有此类类文件,编译器将发出警告也在执行批注处理时生成。如果显式设置此选项,则不会发出警告。请参阅搜索类型

您是否可以尝试隐式声明类文件。

在该警告中,由于处理器在最后一轮中使用“processingOver()”准确地写入新文件,因此产生了该警告

public boolean process(Set<? extends TypeElement> elems, RoundEnvironment renv) {
        if (renv.processingOver()) { // Write only at last round
            Filer filer = processingEnv.getFiler();
            Messager messager = processingEnv.getMessager();
            try {
                JavaFileObject fo = filer.createSourceFile("Gen");
                Writer out = fo.openWriter();
                out.write("class Gen { }");
                out.close();
                messager.printMessage(Diagnostic.Kind.NOTE, "File 'Gen' created");
            } catch (IOException e) {
                messager.printMessage(Diagnostic.Kind.ERROR, e.toString());
            }
        }
        return false;
    }
如果我们从日志中删除我的自定义注释,很难说文件“Gen”实际上是在“第2轮”(最后一轮)上创建的。因此,基本建议适用:如果有疑问,请添加更多日志


这里还有一些有用的信息:

阅读有关“注释处理”的部分,并尝试使用编译器选项获取更多信息:
-XprintProcessorInfo 打印有关要求处理器处理哪些批注的信息。
-XprintRounds打印有关初始和后续注释处理循环的信息。

警告

警告:上一轮中创建的“[Insert class here]”类型的文件 将不接受批注处理

这意味着您正在运行注释处理器,使用javax.annotation.processing.Filer实现(通过javax.annotation.processing.ProcessingEnvironment提供)创建新的类或源文件,尽管处理工具已经决定“在最后一轮中”

这可能是一个问题(因此也是一个警告),因为生成的文件本身可能包含被注释处理器忽略的注释(因为它不会进行下一轮)

以上应该回答你问题的第一部分

这意味着什么?我可以采取什么步骤来清除此警告

(你自己已经弄明白了,不是吗:-)

要采取哪些可能的步骤?请检查批注处理器:

1) 在注释处理器的最后一轮中,您真的必须使用filer.createClassFile/filer.createSourceFile吗?通常在代码块中使用filer对象,如

for (TypeElement annotation : annotations) {
...
} 
(在方法过程中)。这确保注释处理器不会处于最后一轮(最后一轮始终是注释集为空的一轮)


2) 如果您确实无法避免在上一轮中写入生成的文件,并且这些文件是源文件,请欺骗注释处理器,并使用filer对象的方法“createResource”(以“source_OUTPUT”作为位置).

当我读到这个问题时,我最初认为这是因为无法关闭文件。为了测试这一点,我创建了一个简单的处理器,创建、写入但没有关闭文件。我运行了它。它给出了类似但不同的警告。这里的问题是注释处理,而不是类生成。这个特定的代码库取决于类生成。指定-隐式:由于没有生成类,因此没有实际中断生成。-隐式:类对警告没有影响。是的,在我问问题之前就这样做了(可能应该将其放在上面的信息中)。它似乎没有产生任何有用的结果。当它进入最后一轮时,它说没有更多的输入文件,然后发送警告。你能分离出产生此警告的最小测试用例吗?也许可以借助上面的编译器选项。我在OpenJDK源代码中找到了一个测试用例:文件夹“openjdk\langtools\test\tools\javac\diags\examples\ProcFileCreateLastRound"。但我仍然无法理解为什么会在那个地方放置警告。我在原始答案中添加了您问题的可能原因。如果是其他原因,则在看到测试用例之前,我无法告诉您更多。这很可能是一个。在某些方面,我们会在发送文件之前检查处理是否已结束,可能是由于FileRexception of多次打开同一文件。
for (TypeElement annotation : annotations) {
...
}