Java 如果不在类文件中,编译后的代码将存储在其中

Java 如果不在类文件中,编译后的代码将存储在其中,java,compiler-construction,jvm,.class-file,java-compiler-api,Java,Compiler Construction,Jvm,.class File,Java Compiler Api,最近我在阅读时遇到一个问题 在第5页第2章 Java虚拟机要执行的编译代码是 使用独立于硬件和操作系统的二进制文件表示 格式,通常(但不一定)存储在文件中,称为 类文件格式 这个括号是原因,但不一定是原因 问题是, 在这种情况下,编译后的代码将不会存储在类文件中?如果它不会存储在类文件中,那么在哪里以及如何存储 编辑:请注意,问题不是关于类加载器。在java中,类加载器从何处编译二进制取决于它的实现。 可以编写一个类加载器,从数据库、网络、内存或任何其他可思考的位置加载它的类 默认的java使用

最近我在阅读时遇到一个问题

在第5页第2章

Java虚拟机要执行的编译代码是 使用独立于硬件和操作系统的二进制文件表示 格式,通常(但不一定)存储在文件中,称为 类文件格式

这个括号是原因,但不一定是原因

问题是,

在这种情况下,编译后的代码将不会存储在类文件中?如果它不会存储在类文件中,那么在哪里以及如何存储


编辑:请注意,问题不是关于类加载器。

在java中,类加载器从何处编译二进制取决于它的实现。 可以编写一个类加载器,从数据库、网络、内存或任何其他可思考的位置加载它的类


默认的java使用目录或JAR中的文件,因此这就是“通常”的来源,“不一定”只是暗示可能有其他实现。

将编译后的代码存储在.class文件中只是获取JVM可执行代码的标准且更方便的方法,同样的编译代码可以从许多其他来源获得,它可以作为文本或二进制流从数据库、网络连接或运行时的内存中获得,或者

是的,这个问题是关于类加载器的

类加载器是JVM引入类的(唯一)方式。这些类可以是文件、JAR存档、网络上的某个地方、数据库blob中、共享内存中、纸带上(如果您的机器有纸带读取器),甚至可以动态生成

这就是你问题的答案


标准编译器用于编写类文件,但正如Peter所评论的,这不一定是这样。最重要的是,javac命令编写类文件并不意味着我们必须使用这些文件。通常将它们打包到JAR中,然后使用它。

您似乎对如何在内存中生成java类文件更感兴趣,因此:

public class CompileSourceInMemory {
    public static void main(String args[]) throws IOException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new    DiagnosticCollector<JavaFileObject>();

        StringWriter writer = new StringWriter();
        PrintWriter out = new PrintWriter(writer);
        out.println("public class HelloWorld {");
        out.println("  public static void main(String args[]) {");
        out.println("    System.out.println(\"This is in another java file\");");    
        out.println("  }");
        out.println("}");
        out.close();
        JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());

        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
        CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

        boolean success = task.call();

        if (success) {
            try {
                Class.forName("HelloWorld").getDeclaredMethod("main", new Class[] { String[].class }).invoke(null, new Object[] { null });
            } catch (ClassNotFoundException e) {
                System.err.println("Class not found: " + e);
            } catch (NoSuchMethodException e) {
                System.err.println("No such method: " + e);
            } catch (IllegalAccessException e) {
                System.err.println("Illegal access: " + e);
            } catch (InvocationTargetException e) {
                System.err.println("Invocation target: " + e);
            }
        }
    }
}

class JavaSourceFromString extends SimpleJavaFileObject {
    final String code;

    JavaSourceFromString(String name, String code) {
        super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return code;
    }
}
公共类编译源内存{
公共静态void main(字符串args[])引发IOException{
JavaCompiler=ToolProvider.getSystemJavaCompiler();
DiagnosticCollector diagnostics=新建DiagnosticCollector();
StringWriter编写器=新的StringWriter();
PrintWriter out=新的PrintWriter(writer);
println(“公共类HelloWorld{”);
println(“publicstaticvoidmain(stringargs[]){”);
println(“System.out.println(\“这在另一个java文件中\”);”;
out.println(“}”);
out.println(“}”);
out.close();
JavaFileObject file=newJavaSourceFromString(“HelloWorld”,writer.toString());

IterableWell您可以将其保存在一个字节[]在内存中,或者在数据库中。@PeterLiljenberg,这将由编译器定义,对吗?java编译器只是一个java类,您可以调用它,所以是的,输出将由编译器实现决定。阅读官方文档中的更多内容:这是关于从编译代码加载类,如何生成编译代码?Tha这只是另一个特例。代码将在内存中生成/编译,然后由类加载器加载…这是关于获取生成的编译代码,生成编译代码如何?+1是关于从编译代码加载类,生成编译代码如何?检查链接,这也是