JVM将负责将写入其中的方式的人的操作系统(SO)提取。因此,system calls,内存管理,线程和进程,除其他内容外,还为我们编写代码。
通过解释Java,但是在编译过程中生成的字节码,JVM允许我们使用最好的编程语言。 Clojure,Kotlin,Scala和Groovy是在JVM中运行的语言的例子。
编译后,这些语言徒劳无功,用于可以在JVM中解释的字节码结构。让我们想一想用Kotlin和Java编写的简单Olá, mundo!
。
java
public class OlaMundo {
public static void main(String[] args) {
System.out.println("Olá, mundo!");
}
}
生成的Java的字节码:
Compiled from "OlaMundo.java"
public class OlaMundo {
public OlaMundo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String Olá, mundo!
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
kotlin
fun main() {
print("Olá, mundo")
}
字节do docã³digokotlin gerado:
Compiled from "olamundo.kt"
public final class OlamundoKt {
public static final void main();
Code:
0: ldc #11 // String Olá, mundo
2: astore_0
3: iconst_0
4: istore_1
5: getstatic #17 // Field java/lang/System.out:Ljava/io/PrintStream;
8: aload_0
9: invokevirtual #23 // Method java/io/PrintStream.print:(Ljava/lang/Object;)V
12: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #9 // Method main:()V
3: return
}
请注意,Kotlin的字节码与Java代码非常相似。但是,如何在JVM中收取这些字节码?
JVM解释的过程
bytecode java 的所有编译文件都在其名称的末尾获取.class
。该后缀是通知JVM的一种方法,这是准备加载的Java类。此过程称为加载。
此加载是由A 类加载器进行的,该基本上将在Class
类型内存(java.lang.Class
实例)中生成一个对象,其中该类的元式形式将携带元 - 形式。名称,超类参考,母亲的名称©all等。
JVM有多个Class Loader
,并遵循特定的命令,以促进某种安全性。例如,如果我们创建一个名为String
的类,例如确保代码的其他部分实际使用Koud6类和我们创建的类?
要了解有关类加载程序的更多信息,值得一提的是JVM https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-5.html#jvms-5.3.1
加载阶段后,启动链接步骤。在此阶段,可以验证字节码是否格式化(验证步骤),遗产变化的空间分配(准备阶段)和),以及必要时,可以解决所讨论的类和对象参考的解决方案(解决阶段)。
这个分辨率的阶段可以在下一步之前或之后发生,这是初始化步骤。最后一步是实际上将初始化对象的变量并准备好使用。
在下图中,有一个简单的这些阶段的说明:
我们现在知道每次在JVM中创建对象时会发生什么,但是当我们不需要此对象时会发生什么?
关于内存模型的一点
在诸如C之类的语言中,我们需要在必要时分配和脱位内存空间。如果在此分配过程中,应用程序请求操作系统的空间,而无法获得必要的空间,则应用程序会出现错误。
如果在JVM中运行的方式,记忆分配的整个过程都是透明的。 JVM创建了虚拟内存空间,其中应用程序,即Java,Kotlin等,与此虚拟内存与计算机的真实内存进行交互。基本上通过JVM中的内存空间:stack
,heap
和method area
。
stack
是线程的空间。在其中,是原始类型的注册变量,一部分执行结果,母亲的回报等,以及其他类型的数据和元数据。根据JVM的规格esses tipos de dados são armazenados em koude11。
heap
中的
实际上存储了对象。每次给出new Obj();
时,这个新对象都会存储在堆中,并且对其进行引用在某些堆栈框架中。因此,heap
比stack
更大。
当Koud8中的这些对象丢失其参考时,JVM可以自动将此对象识别为垃圾并从内存中收集。为此,她使用垃圾收集算法或GC。
每个JVM实现都可以具有一种或多种GC算法,具有不同的优化。该规范仅定义了该系统中应收集Koud8中的对象。
有几种GC算法和各种优化它们的方法。 每个算法具有Bânus和ânus,并且可以应用于不同的使用应用程序和情况。由于它是一个复杂而广泛的主题,因此它逃脱了本文的一些范围。但是,未来的Yuri应该写一些有关该主题的文章。
目前,我们只知道这些算法存在,因此,由于它们,我们不必担心管理在JVM
下运行的应用程序的记忆。知道吉特
JVM解释的代码通常比母亲的母亲慢,即直接在计算机上运行的方式,而无需中介(就像虚拟角一样)。
考虑解决此问题的思考,JVM的规范介绍了JIT的概念,或者 just-Impime Compiler 。
jit只不过是由JVM执行并将Java字节码转换为本地的另一个编译器。除了编译JVM的本机外,JVM还可以对代码进行其他性能改进,以便更加皱眉执行。
每个JVM实现都有其自己的算法以及对此进行编译和优化的方法,但基本上是通过最执行的时间执行的摘录。每次使用一个JVM
对于那些使用Java或其他支持的语言编程的人来说,JVM是一项很好的资产。它具有良好的规范和用于使用案例和不同需求的几种实施。了解此工具的更多信息可以帮助我们解决错误,改善性能并更加稳健和弹性的过程。