最近我在阅读Java虚拟机的结构
时遇到了查询在第5页的页面上。2,
编译的代码将由Java Virtual Machine执行 使用硬件和操作系统独立的二进制代表 格式,通常(但不一定)存储在文件中,称为 班级文件格式。
该括号,但不一定是原因。
问题是,
在哪种情况下,编译的代码不会存储在类文件中?如果它不会存储在类文件中,那么在哪里以及如何存储?
编辑:请注意,问题与classloader无关。
您似乎对如何在内存中生成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;
}
}
来源:在内存汇编
中这将在内存中生成一个类,而无需任何Java源或编译类的外部表示。
在java中,classloader从其实现取决于其实现。可以编写一个从数据库,NET,内存或任何其他可疑位置从数据库中加载其类的类加载程序。
默认Java UrlClassloader使用目录或罐子中的文件,因此"通常"来自的地方,"不一定"只是可能还有其他实现的提示。
将编译的代码存储在.class文件中只是获得JVM可执行代码的标准和更方便的方法,但是,可以从许多其他来源获得相同的编译代码,IT可以从数据库或网络连接或从运行时内的内存中作为文本或二进制流获取,检查此示例或该示例
是的,这个问题是关于classloader的!
classloader是JVM带来的(唯一)类。这些类可以在文件中,jar档案,网络上的某个地方,数据库斑点,共享内存,纸带上(如果您的计算机有纸带读取器),或者甚至可以在飞行中生成。
所以,这是您问题的答案。
标准编译器用来编写类文件,但是,正如彼得所说的那样,不一定是这样。而且,最重要的是,仅仅是因为Javac命令写入类文件,这并不意味着我们必须使用这些文件。通常将它们包装在罐子中,然后使用它。