JAVA与JVM

JVM(JAVA虚拟机)

虚拟机分为栈和堆:

  • 堆:
    回收:堆是由GC来负责回收的。
    存储类型:主要存储对象、静态成员变量随类的类型一起存储在对上。
    存储大小:堆是动态生成内存大小。
    存储周期:生存期无需通知编译器。
    存取效率:存取慢。
  • (线程)栈:
    回收:线程执行完自动回收。
    存储类型:栈中主要存储基本类型变量(小写的int等类型)、调用栈和本地变量。数据共享。
    存储大小:生成数据大小确定。
    存储周期:生存期确定。
    存取效率:存取快。

Tips:1、如果两个线程(中的本地变量)调用了同一个对象,那么他们都会拥有这个变量的私有拷贝。

  1. 在web环境中,Tomcat启动会占用一个线程,而用户每次访问API,Tomcat会额外创建一个线程。

JMM(JAVA内存模型)

JMM是指JVM对于内存是如何操作的一个规范。

  1. JMM规定了一个线程何时如何看到修改后共享变量的值,以及在必须时,如何同步的访问共享变量。它要求调用栈和本地变量存放在线程栈上,对象存放在堆上,线程间的通信必须要经过主内存。它定义了8个基础操作。
JAVA与JVM_第1张图片
操作规则
  1. 一个变量在同一时刻,只允许一条线程对其执行Lock操作,而该线程可以对该变量执行n次Lock,如果需要unlock,则同样需要执行n次。
  2. 如果一个变量执行了锁(包括synchronized和Lock等)操作,那么他会清空工作内存中的值,在执行引擎使用此变量之前,需要重新执行load或者assign来初始化值。
  3. 若一个变量没有被lock,则不允许执行unlock。也不允许执行其他线程的unlock。
  4. 在执行解锁操作之前,必须先把该值同步回主内存。
  5. read和load操作,可以不连续执行,但必须先后执行。同理于store和write操作。

classloader(类加载机制)

  1. 类加载的方式
  • 显式:通过Class.forName("XXX")来加载;
  • 隐式:通过new来隐式调用classLoader到JVM;

在类的加载过程中,所有类都是从父类采用 双亲委派原则 加载过去的(而不是直接去加载这个类的)。有三个最基本的父类加载器Bootstrap class loader(所有类的父类加载器,包括后面两个)、extension class loader、application class loader。

Bootstrap class loader:加载基本的jdk包。
extension class loader:加载第三方jar包。
application class loader:加载应用程序和用户自定义类。
双亲委派原则:

其工作流程为:

  1. 从已经加载过的类中查找是否加载过此类,若加载过则直接返回;
  2. 若未加载,则委托父类加载器去加载,层层委托,直到最顶层的父类;
  3. 若所有的父类加载器都不能加载该类时,由当前类自己加载,并放入自己的缓存中。

采用这种形式的加载,主要是基于安全,避免两个同名的类加载冲突。

GC(回收机制)

什么是GC

GC即垃圾回收。对于程序中不可达的引用或者变量等进行资源回收。

GC的常用算法

1. 计数法
所有的变量从一出生就被标记了使用次数,出生标记起始数字start,在该线程中,每一次使用会记录次数+1,每一次用完会减1,若最后减为end(变量达到死亡的数值),回收该变量。
优点:使用简单,每个对象分配一个计数器。
缺点:对于循环或递归效果很差。
2. 标记-清除法
停止所有工作,标记扫描过的活跃的对象,然后将没有标记的清除掉。
优点:可以解决循环问题。
缺点:1 所有都要停止;2 当对象很多时,效率不高;3 造成内存碎片。

Tips:内存碎片,即内存中断断续续存在的部分。每个一段会有一段内存,这样会导致申请大对象时,无法申请。

3. 复制法
开辟两块空间,某一时刻只有一个空间活跃,当活跃的空间快满时,将活跃空间里的活对象移动到不活跃的空间中,此时不活跃的空间升为活跃。较于标记-清除法来说以空间换时间。

优点:1 不用停止;2 只扫描活对象;3 没有碎片化。
缺点:1 空间开销大;2 复制开销。

4. 标记-整理法
该方法时汲取于清理法复制法。首先扫描所有活跃的对象,并标记所有活跃的对象,然后清除未标记的对象,并将活跃的的对象复制到堆得底部。

优点:1 不用停止;2 只扫描活对象;3 没有碎片化;4 没有空间开销。
缺点:1 复制开销。

JAVA与GC

java中的GC没有指定的用法,有可能以上都用到。
java中还存有一种方法分代收集法。针对于指定的区域进行回收。可以缩小收集范围,一块一块收。涉及到的GC有:
Minor GC:也叫young GC。
作用范围:年轻代空间(Eden和Survivor区域)
算法:标记-整理法。
触发条件:1 young gen满了
2 要分配的对象大于剩余空间;
Major GC:也叫old GC。
作用范围:老年代。
触发条件:1 old gen满了
Full GC:包含Minor GC和Major GC。
作用范围:整个堆——年轻代和老年代。
触发条件:1 如果young GC的平均晋升大小比old gen的剩余大小大

内存泄漏和内存溢出

内存泄漏:memory leak。是指堆内存由于某种原因,无法释放或未释放,造成系统资源的浪费。
内存溢出:即OOM(OutOfMemory)。程序在申请内存时,没有空间供其使用,或已申请的内存小于要使用的内存。

优化

一般设置Xmx和Xms一样。
Xss为每个线程的大小。默认为1M。在相同物理内 存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
Xmn大小推荐为整个堆的3/8。
参考:常用 JVM 命令参数。
设置JVM参数,查看堆大小。

JMM参考:https://www.jianshu.com/p/be923a7beb2c。

参考:https://blog.csdn.net/lzxadsl/article/details/50159939。

你可能感兴趣的:(JAVA与JVM)