一聊到JVM,首先要想到为什么需要虚拟机
因为java的跨平台,就是通过虚拟机来实现的
JVM的原理
1。类加载机制
jvm类加载机制:加载,验证,准备,解析,初始化
类加载机制需要知道的是双亲委派,会先把请求委派给父类加载
Bootstrap Classloader>Extension ClassLoader>Application Classloader
如何验证呢:自己创建一个class类,如创建一个User
User.class.getClassLoader().toString() 输出appClassloader
User.calss.getClassLoader().getParent.toString() 输出ExtClassLoader
这边不能输出bootstrap ClassLoader 会报错NullPointerException
好处:防止内存出现多分同样的字节码,保证类的唯一性
如何打破双亲委派,继承ClassLoader,重写findClass,loadClass方法
2。内存管理
每一个JVM都会包含方法区,java堆,java栈,本地方法栈,指令计数器
方法区和java堆是线程共享的
java栈,本地方法栈,指令计数器是每一个线程都会有的,是线程隔离的
如何撑爆堆呢?死循环,会抛出OutOfMemoryError
如何撑爆栈(stack)递归调用,会抛出StackOverFlowError
3。垃圾回收
GC(重灾区)
要知道gc的几个算法,标记清除算法,复制算法,标记整理算法
jdk1.7和jdk1.8的关于gc的永久带的区别,1.8把永久带不再放到堆中,放到了磁盘中
什么时候会gc?
当对象没有被引用到的时候,可以自己gc,System.gc()
GC的时候对象会被分为强引用,软引用,弱引用,虚引用
finalize()引用了对象的话,可以使对象这一次gc的时候不会被回收
后面就聊一下关于新生代,老年代和永久带
我的理解是:年轻代存放的是新的对象,就是引用次数比较少的,随着gc,会给这些对象标记被引用的次数,次数达到一定的量会被放到老年代中,所以两个代的算法是不一样的,年轻代用的是复制算法,老年代用的是标记整理算法。
新生代的默认的收集器:Paraller Scavenge
老年代的默认的收集器:Paraller Old
还有就是如何给jvm调参数,idea是tomcat中的VM options