来回看jvm的东西,再拿起来还是记不住,--XX***参数一大堆,各种组件和名词,根本记不住,调优起来缺不清楚怎么设置这些参数。看一些经验行的比例,在解决问题的时候还是不清楚。
原因是你没有正真搞清楚JVM
怎么解决? 你自己设计一个JVM,过一遍逻辑,把JVM中各部分结构化,有机的组合在一块,存在是为了解决问题,妥协是为了平衡优缺点。
有C,C++语言了,也有局限,对平台依赖严重,空间需要自己管理,很麻烦一不小心就遗忘导致了内存泄露。怎么解决?
Jvm:Java visual machine。
抽象出字节码,JVM去根据字节码适配到各个平台就行,上面的操作就不需要考虑平台差异性喽。

基于Jvm语言包括:Java,kotlin,Scala,Clojure,Groovy,Jython,JRuby,Ceylon,Eta,Haxe
需求:
字节码就是执行的逻辑,加载到内存,需要所有人都可以看的到
静态变量是公用的,放哪呢
根据类创建的对象,这部分得可以共享,否则一个用户干点事所有的基础对象都得自己创建。对象包括放对象引用的地址信息,对象数据空间。
每个用户都有自己的隐私,也需要给每个用户独占的一块空间
最后是控制代码执行的指针,即:现在代码执行到那了,也需要保存下来。对单核机器来说,当前需要执行的指针只有一个,如果要挂起就保存起来,用当前执行的用户的指针就行
上面都是静态的空间,下来说动的部分:
首先需要加载字节码,其次是需要根据字节码执行代码,分配空间,创建线程,按照方法调用逻辑执行,执行的过程中对没用的垃圾对象要及时回收
组件架构图:

蓝色:线程独占
橙色:共享

有一个类来将class文件加载到内存中,放在方法区域中
安全检查这个类,确保加载的类符合 JVM 规范和安全
如果没问题,就给静态变量分配空间,并初始化,这类数据是类唯一的,可以也放在方法区内。
如果static String a=”abc”,需要将”abc”放在常量池中,并将a赋值常量池值”abc”的引用。
这时这个类就就绪了。
卸载,GC将字节码删除的过程
一个和一批加载自然不同,比如:java本身提供一些类,如果你的类和java的类重名了咋办,如果没有啥规则就乱套了。
再一个,如果java的字节码,你自己写个类加载器,那加载到内存中谁知道出现啥问题,你也不清楚人家底层呀,更模板模式一样,即使允许你自己写类加载器,也只给你预留部分你自己可以实现的部分才可以。
重名咋办:那优先用java提供的
类加载器:java提供的类由Java自己的类加载器加载;自己写的类,java给个默认的加载器,也可以自定义一个加载器,但必须是继承人家的ClassLoader类,只有部分方法可以自定义。
垃圾回收:1. 哪些算是垃圾;2. 怎么回收。
垃圾认定:程序没法找到这个对象,自然就没用了,表现为这个对象的引用是否被别人保留,没有引用也就没法找到该对象了。或者给每个对象搞一个计数器,谁用记录,最后计数器为0就没人用了。
怎么回收:
实际逻辑:标记操作同时进行,从根(GCRoot)开始,找有用的对象,找到就改复制复制,该压缩压缩。


结合实际设计:任何一种压缩算法都不是最优的,最好情况是集成所有算法的有点。那就需要对对象分类了,一个进程启动后启动类对象基本不变,方法中局部变量用完就得回收,线程之间共享的对象就不确定啥时候该回收了。很容易分为:确定永久不变的;王八级;朝生夕死级;不确定的生存时间的。 还有一个维度就是大小,大对象很很好性能,尽可能不动,动的时候尽可能就是回收(只复制活对象,垃圾是不动的)。
除了从语法上就可以看出永久不变的,直接放在一个区域。
其他其实都是存活时间[一次gc,无穷大),可以gc抽象为过年,每一次gc没有死掉的,对象长一岁。那这个节点怎么确定,基于统计数据吧。

详细逻辑分析:
持久区域就没必要花了,反正也不GC
两个问题:
直接给答案吧:
我个人意见是统计出来的,有人说15是因为存储空间原因,我不以为然,如果统计数据是32岁最合适,我就不信JVM不会设计一个超过4b的存储空间来存储这个值。
JVM内存模型(通俗易懂)_抵制平庸 拥抱变化的博客-CSDN博客_jvm内存模型