【Javaファイルはエンコードから実行まで次のようなプロセスを経ます】 【JVMのメモリ分割】 【オブジェクトの作成プロセス】 【ガベージコレクションのアルゴリズム】

【Javaファイルはエンコードから実行まで以下のプロセスを経ます】

1.コンパイル: .java ファイルを .class ファイルにコンパイルします;
2.ロード: .class ファイルを JVM メモリにロードし、ロード (クラス情報をメモリに読み取る) -> 接続 (接続) を実行します。フェーズはクラスの情報を検証し、クラス変数にメモリ空間を割り当て、デフォルト値を割り当てます) - 「初期化操作 (静的ブロックの内容の初期化を実行し、静的変数に対する実際の代入操作を実行します); 3. 解釈:
.classファイルをオペレーティング システムが認識できるコマンド コードに解釈します;
4.実行: コマンド コードをシステム ハードウェア デバイスに送信して、操作を実行します。

[JVMメモリパーティション]

ソース コードがコンパイルされてロードされた後、実行後にこの情報はどのように分類され、JVM に保存されるのでしょうか?

JVM は、さまざまなデータの特性に応じて、メモリを
メソッド領域、仮想マシン スタック、ローカル メソッド スタック、プログラム カウンタ、ヒープのいくつかの領域に論理的に分割します。

1、方法区:JVM方法区是用于保存已经被虚拟机加载的类元信息
 (包括类的版本、字段、方法、接口和父类等信息)、运行时常量信息(static、final定义的常量)、
 字符串常量信息(String a="dfc")。

2、虚拟机栈:栈这部分区域主要是用于线程运行方法的区域,此区域属于线程私有的空间,
每一个线程创建后都会申请一个自己单独的栈空间,每一个方法的调用都会对应着一个栈帧。
栈帧里存储着方法的局部变量表(保存着变量的数据)、操作数栈(进行运算时存放数据的空间)、
动态连接(指向常量池的引用)和方法返回地址(当前方法返回后的数据存放的地方)信息。
每调用一个方法都会生成一个新的栈帧,调用方法的过程就是一个压栈和出栈的过程。

3、本地方法栈:由于java需要与一些底层系统如操作系统或某些硬件交换信息时的情况,这个时候就需要
通过调用native本地方法来实现,本地方法栈和虚拟机栈功能差不多,区别在于本地方法栈是虚拟机调用
native方法时使用的。

4、程序计数器:程序计数器是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的
行号指示器,程序计数器记录着某个线程当前执行指令的位置,此区域属于线程隔离区。

5、堆内存主要是用来存放我们运行过程中创建的对象数据,根据对象所生存时间长短的特性在逻辑上分为
 新生代和老年代。


对于JVM而言,大部分对象都是属于一个朝生夕死的状态,这部分对象随着方法的调用而创建,
方法的结束而消亡,只有少部分的对象会长久的留在JVM 内存中,所以根据这样的特性JVM 把内存分为了
新生代 和老年代两个区,一般情况新创建的对象会放到新生代中,只有经过一定次数的GC后还没有被回收的对象,
我们认为这部分对象在未来也会长时间存在,所以会把这部分的对象转移到老年代的区域中去。
新生代分为eden区(存放新创建的对象)和suivior区(分为S1和S2)

【オブジェクトの作成手順】

1、编译:经过编译后Person.java 会生成一个Person.class文件。

2、装载:Person.class经过加载后,会把类的相关信息加载到JVM内存中,
解析出类的描述信息会保存到Metaspace,同时这里会生成一个代表这个类的java.lang.Class对象,
作为这个类的各种数据的访问入口。

3、连接:连接阶段会对静态变量的值进行默认赋值,此时Person类的staicVariabl 赋值为0;

4、初始化:
   1)、首先会对Person类的静态变量staicVariabl 进行真正的赋值的操作(此时staicVariabl =1)。
   2)、然后收集类的静态代码块内容,生成一个类的<clinit>() 方法并执行(此时staicVariabl =2)。
   
5、对象创建:
 1、构建对象:首先main线程会在栈中申请一个自己的栈空间,然后调用main方法后会生成一个main方法的栈帧。
 2、初始化对象:然后执行对象内部生成的init方法,初始化成员变量值,同时执行搜集到的{}代码块逻辑,
 最后执行对象构造方法。
 3、引用对象:对象实例化完毕后,再把栈中的Person对象引用地址指向Person对象在堆内存中的地址。

【ガベージコレクションアルゴリズム】

1. 二度と使用されないオブジェクトをゴミと呼びます。

2. オブジェクトがリサイクル可能かどうかを判断するにはどうすればよいですか?

1、引用计数法
引用计数法是为对象添加一个引用计数器,

2、可达性分析法
可达性分析法是通过以所有的“GC Roots”对象为出发点,如果无法通过GC Roots的引用追踪到的对象,
那我们认为这些对象就不会再次被使用了,现在主流的程序语言都是通过可达性分析法来判断对象是否存活的。

3. ガベージコレクションアルゴリズム

1、标记清除法
标记清除法是先找到内存里的存活对象并对其进行标记,然后统一把未标记的对象统一的清理。
但是会造成不连续的内存空间。

2、标记复制法
首先它把内存划分出三块区域,一块用于存放新创建的对象叫Eden区,另外两块则用于存放存活的对象
分别叫 S1区和S2区。回收的时候会有两种情况,一种是把Eden和S1区的存活对象复制到S2区,
第二种是把Eden和S2区的存活对象复制到S1区 ,也就是说S1区和S2这两块区域同时只会有一块使用,
通过这种方式保证始终会有一块空白的q区域用于下次GC时存放存活的对象,而且原来的区域不需要
考虑保留存活的对象,所以可以直接一次性清除所有对象,这要既简单直接同时也保证了清除的内存区域
的内存连续性。

3、标记整理法
标记整理法分为标记和整理两个阶段,标记阶段会先把存活的对象和可回收的对象标记出来;
标记完再对内存对象进行整理,这个阶段会把存活的对象往内存的一端移动,移动完对象后
再清除存活对象边界之外的对象。

4. さまざまなガベージコレクションアルゴリズムの適用シナリオ

3 つのガベージ コレクション アルゴリズムを理解すると、完璧なアルゴリズムは存在しないことがわかります。各アルゴリズムには独自の特性があるため、特定のシナリオに基づいて適切なガベージ コレクション アルゴリズムを選択するしかありません。

1、标记清除法
特点: 简单、收集速度快,但会有空间碎片,空间碎片会导致后面的GC频率增加。
适合场景:只有小部分对象需要进行回收的,所以标记清除法比较适用于老年代的垃圾回收,因为老年代一般存活对象会比回收对象要多。

2、标记复制法
特点:收集速度快,可以避免空间碎片,但是有空间浪费,存活对象较多的情况下复制对象的过程等会非常耗时,而且需要担保机制。
适合场景: 只有少量对象存活的场景,这也正是新生代对象的特点,所以一般新生代的垃圾回收器基本都会选择标记复制法。

3、标记整理法
特点: 相对于标记复制法不会浪费内存空间,相对标记清除法则可以避免空间碎片,但是速度比其他两个算法慢。
适合场景: 内存吃紧,又要避免空间碎片的场景,老年代想要避免空间碎片问题的话通常会使用标记整理法。

おすすめ

転載: blog.csdn.net/Little_Arya/article/details/129739016