初始化
简单的说,就是在内存中开申请一片空间。
比如:变量、对象。
所以为什么引用有初始化才能用。
堆、栈
栈:连续的空间,放置局部变量;
堆:不连续的空间,用来存放new对象;
堆(Heap)
new 出来的对象都存放在堆里。这里还有常量池。
栈(Stack)
又叫堆栈。JVM为每个新创建的线程都分配一个栈。也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。JVM对栈只进行两种操作:以帧为单位的压栈和出栈操作。
OopMap
Ordinary Object Pointer
记录对象在内存的精确位置,以帮助 HotSpot 快速且准确的完成 GC roots枚举。
HotSpot 不可能为每条指定都生成 OopMap,只有在特定位置才会生成。这个特定位置称做:安全点。
即,程序执行时并非在所有地方都能停顿下来做GC,只有在到达安全点时才能暂停。
局部变量表
Java中方法的局部变量是放在虚拟机栈的局部变量表里面,形参也算一个。
本地变量表,就是局部变量表,只是翻译不同。
代码说明
public static void main(String[] args) {
byte[] waste = new byte[6 * 1024 * 1024];
int new_var = 0;
System.gc();
}
反编译得到:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=3, args_size=1
0: ldc #2 // int 6291456
2: newarray byte
4: astore_1
5: iconst_0
6: istore_2
7: invokestatic #3 // Method java/lang/System.gc:()V
10: return
结果:
locals=3
也就是说局部变量表长度是3.
原子性 和 可见性
原子性:
即,不可分割性,白话就是操作不允许被打断。为了保证不被打断就要使用同步的方式,如:synchronized。
a++ 实际是 a = a + 1; 这不是一个原子操作。
非原子操作就会存在线程字全问题。
可见性:
是指线程之间的可见性。
一个线程修改的状态,对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。
这么说是因为每个线程的内部都有自己的工作内存,当从内存顺读取一个变量后,这部份变量就会在线程内存有一份独立的副本,当前线程操作的是这个独立副本。
那么,如何实现呢可见性呢,有请 volatile。
volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。
GC 概念
Full GC
Full GC 针对整个新生代、老生代、元空间(metaspace,java8以上版本取代perm gen)的全局范围的GC;
Minor GC
Minor GC 在Hotspot JVM实现的Serial GC, Parallel GC, CMS, G1 GC中大致可以对应到某个Young GC和Old GC算法组合;
Major GC
Stop The World
GC roots
GC root 对象是有多种,而非指某一个。
包括以下几类对象:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象;
2.方法区中类静态属性引用的对象;
3.方法区中常量引用的对象;
4.本地方法栈中JNI(即一般说的Native方法)引用的对象;
简而言之就是:方法运行时,方法中引用的对象;类的静态变量引用的对象;类中常量引用的对象;Native方法中引用的对象。
网友评论