JVM是JavaVirtualMachine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
类加载过程实质是读取.class文件生成对应的java.long.Class对象,并将类的静态数据结构初始化的过程。
以下2,3,4统称【连接】 1.加载 通过一个类的全限定名获取定义此类的二进制字节流,并将该流的数据存储到方法区中。 2.验证 这一阶段主要是为了确保Class文件的字节流中包含的信息符合虚拟机的要求,并且不会危害虚拟机自身的安全。 3.准备 是正式为类变量分配内存并设置初始值的阶段,这些变量所使用的内存都将在方法区分配 4.解析 是将虚拟机常量池内的符号引用替换为直接引用的过程.(用内存引用替代io引用) 5.初始化 类初始化的主要工作时为了静态变量赋程序设定的初值
作用是加载.class文件,将新建的对象放入堆里面,引用(地址)放到栈,其中引用指向堆里面对应的对象。
分类: 1)启动类(根)加载器 Bootstrap ClassLoader:负责加载jre\lib目录下的rt.jar包 2)扩展类加载器 Extension ClassLoader:负责加载jre\lib\ext目录下的所有jar包 3)应用程序(系统类)加载器 Application ClassLoader:负责加载用户类路径上所指定的类库,如果应用程序中没有自定义加载器,那么次加载器就为默认加载器。
package java.lang;
public class String {
public static String toStrings() {
return "Hello";
}
public static void main(String[] args) {
System.out.println(String.toStrings());
}
}
报错如下:
错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application
2.类装载器 类装载器在3个方面对Java沙箱起作用:
它防止恶意代码去干涉善意的代码; 它守护了被信任的类库边界; 它将代码归入保护域,确定了代码可以进行哪些操作。 类装载器采用的机制是双亲委派模式。
3.存取控制器 存取控制器可以控制核心API对操作系统的存取权限,而这个控制的策略设定,可以由用户指定。
4.安全管理器 是核心API和操作系统之间的主要接口。实现权限控制,比存取控制器优先级高。
5.安全软件包 java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:安全提供者、消息摘要、数字签名、加密、鉴别等。
栈有可能放的东西:8大基本类型 + 对象的引用 + 实例的方法
栈运行的原理:每执行一个方法,都会产生一个栈帧(可以理解为一个对象,包括:方法索引,输入输出参数,本地变量,Class File,父帧,子帧)
栈如果满了,就会 StackOverFlowError
(1) 堆内存分为年轻代(Young Generation)、老年代(Old Generation)
年轻代又分为Eden和Survivor区。
(2) 堆内存用途: 存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收。
(3) 堆与分代 新生成的对象首先放到年轻代Eden区,当Eden空间满了,触发Minor GC,存活下来的对象移动到Survivor0区,Survivor0区满后触发执行Minor GC,Survivor0区存活对象移动到Suvivor1区,这样保证了一段时间内总有一个survivor区为空。经过多次Minor GC仍然存活的对象移动到老年代。 老年代存储长期存活的对象,占满时会触发Major GC=Full GC,GC期间会停止所有线程等待GC完成,所以对响应要求高的应用尽量减少发生Major GC,避免响应超时。 Minor GC : 清理年轻代 Major GC : 清理老年代 Full GC : 清理整个堆空间,包括年轻代和永久代 所有GC都会停止应用所有线程。
(4) GC处理流程:
格式:-XX:[+-] 表示启用或者禁用name属性。
例子:-XX:+UseG1GC(表示启用G1垃圾收集器)
1.尝试扩大堆内存(设置 VM Options),查看结果: -Xms1024m -Xmx1024m -XX:+PrintGCDetails
如果解决,说明是默认分配的内存不够 2.分析内存,看一下哪里出现了问题(专业工具)
内存快照分析工具: Jprofile、 MAT (eclipse集成使用),分析dump出来的文件 工具作用: 分析 Dump 内存文件,快速定位内存泄露 探知堆中的数据,获得大的对象 …
优点:不会像标记-清除算法那样产生大量的碎片空间。
缺点: 如果存活的对象过多,整理阶段将会执行较多复制操作,导致算法效率降低。
内存效率(时间复杂度):复制算法 > 标记清除算法 > 标记压缩算法 内存整齐度:标记压缩算法 = 复制算法 > 标记清除算法 内存利用率:标记压缩算法 = 标记清除算法 > 复制算法
GC:分代收集算法
年轻代特点存活率低,所以适合于复制算法; 老年代存活率高,适合于标记清除+标记压缩混合实现
JMM是用来定义一个一致的、跨平台的内存模型,是缓存一致性协议,用来定义数据读写的规则。
内存模型可以理解为在特定的操作协议下,对特定的内存或者高速缓存进行读写访问的过程抽象描述,不同架构下的物理机拥有不一样的内存模型,Java虚拟机是一个实现了跨平台的虚拟系统,因此它也有自己的内存模型,即Java内存模型(Java Memory Model, JMM)。
它不是对物理内存的规范,而是在虚拟机基础上进行的规范从而实现平台一致性,以达到Java程序能够“一次编写,到处运行”。
Java Memory Model(Java内存模型), 围绕着在并发过程中如何处理可见性、原子性、有序性这三个特性而建立的模型。
一个操作不能被打断,要么全部执行完毕,要么不执行。在这点上有点类似于事务操作,要么全部执行成功,要么回退到执行该操作之前的状态。
一个线程对共享变量做了修改之后,其他的线程立即能够看到(感知到)该变量的这种修改(变化)。 通常使用volatile关键字来处理,volatile的特殊规则保证了volatile变量值修改后的新值立刻同步到主内存,每次使用volatile变量前立即从主内存中刷新,因此volatile保证了多线程之间的操作变量的可见性,而普通变量则不能保证这一点。除了volatile关键字能实现可见性之外,还有synchronized,Lock,final也是可以的。
使用Lock接口的最常用的实现ReentrantLock(重入锁)来实现可见性:当我们在方法的开始位置执行lock.lock()方法,这和synchronized开始位置(Monitor Enter)有相同的语义,即使用共享变量时会从主内存中刷新变量值到工作内存中(即从主内存中读取最新值到线程私有的工作内存中),在方法的最后finally块里执行lock.unlock()方法,和synchronized结束位置(Monitor Exit)有相同的语义,即会将工作内存中的变量值同步到主内存中去(即将线程私有的工作内存中的值写入到主内存进行同步)。
final关键字的可见性是指:被final修饰的变量,在构造函数数一旦初始化完成,并且在构造函数中并没有把“this”的引用传递出去(“this”引用逃逸是很危险的,其他的线程很可能通过该引用访问到只“初始化一半”的对象),那么其他线程就可以看到final变量的值。
对于一个线程的代码而言,我们总是以为代码的执行是从前往后的,依次执行的。这么说不能说完全不对,在单线程程序里,确实会这样执行;但是在多线程并发时,程序的执行就有可能出现乱序。用一句话可以总结为:在本线程内观察,操作都是有序的;如果在一个线程中观察另外一个线程,所有的操作都是无序的。前半句是指“线程内表现为串行语义(WithIn Thread As-if-Serial Semantics)”,后半句是指“指令重排”现象和“工作内存和主内存同步延迟”现象。 Java提供了两个关键字volatile和synchronized来保证多线程之间操作的有序性,volatile关键字本身通过加入内存屏障来禁止指令的重排序,而synchronized关键字通过一个变量在同一时间只允许有一个线程对其进行加锁的规则来实现 在单线程程序中,不会发生“指令重排”和“工作内存和主内存同步延迟”现象,只在多线程程序中出现。
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
1.static保证唯一性,就是在主内存中是唯一的变量。
2.volatile是保证可见性,就是指在工作线程和主内存的数据的一致性,改变了工作线程中volatile修饰的变量,那么主内存也要发生更新。
volatile和static一起使用不矛盾。因为static修饰只能保证在主内存的唯一性,如果涉及到其他工作线程,改变参数可能就会导致static修饰的变量的内容无法同步,所以static和volatile可以一起使用,因为他们管的地方是不一样的,互不影响。