zoukankan      html  css  js  c++  java
  • 学习笔记-java两种核心机制-JVM和GC

    我们知道C C++是依靠操作系统运行,而我们的Java不一样,是依靠jvm

    而这里看到JVM又想引出什么jre(Java运行环境),jdk(Java开发工具包)

    这两个经常用到的,也很简单就是使用JDK的开发工具完成JAVA的程序,交给JRE去运行。具体知道jdk>jre,我记得当初看jdk包的时候里面还含有jre,所以这也是为啥eclipse IDEA只需要导入jdk即可

    而我们只运行java程序的话就按一个JRE就行了,小很多

    首先让我们来看一张图了解一下什么是jvm(JAVA虚拟机)

    Java虚拟机不像vm ware一样能直接虚拟硬件模拟一台虚拟机,但是他本身作为一个虚拟机,也是有自己本身的指令集的,只要匹配的文件符合JVM对于加载文件的要求就可以

    所以,我们现在的很火的kotlin(与JAVA很兼容)是不是也理所当然也可以了。可以说JVM 就是一个规范。

    而怎么看这些规范和指令集呢,平常我们又不用,那我们只需要用的时候对照看看就行了

    当我们随意哪一个.class文件进行javac -xxx后会生成一个白色.class  字节码文件

    如图

     

     看不懂的所以需要反汇编

    找到反汇编的指令即可

     

     

     然后我们比如这里就有https://www.jianshu.com/p/bc91c6b46d7b找到指令集,然后对比学习,就了解的上面的coonst1等指令了,

    而前面的数字是程序计数器用来标记标记执行位置这些用的

    接下来我们再看底层点

     

     而我们都知道Java 堆----------------------堆存放由new创建的对象和数组-------------------------------------------------------------------------

    而---------------------- 栈(线程)每一个栈都有单独的线程从栈这个大线程中分配得来(当然除了线程内存还有我们的局部变量等)

    如图

     因为不同的线程调用不同的方法都有不同的局部变量,所以都需要单独的栈内存区域。这就是栈内部的栈内存分配,而这时就引出--栈帧,在我的理解就是指针,一种数据结构,高效快捷的

    找到并且运用什么插删移等

     而栈我们学了数据结构都知道是先进后出!我们就可以想一想,最先调用是main方法,所以栈线程main分配了一个线程,然后main里面调用了compute这个方法,这个方法又

    得分配一个线程对不,所以就又分配,但是是不是后进,所以他先出,这样也才正常,因为我们的main 从生命周期来看也确实比compute久一点

     

     

    而我们知道new 的对象都是在堆中的,如果new多了对象会怎样

     

     对象多了就需要回收,怎么做到底回收哪些呢,为什么会有什么年轻代,老年代呢。往下:

    GC垃圾回收

    首先我们知道c c++是程序员回收,手动编写代码回收内存。      优点:随时随地高效回收,可控的,          缺点:这就很有可能遗忘或者泄露等问题造成内存一直不回收

    而我们Java是自动的,开了一个系统级线程自动去检查哪些内存不用了然后回收掉。   优点:自动省心,   缺点:回收慢不及时,不是可控的

    但是现在因为硬件已经发展起来的原因,回收慢这些问题已经影响不大了,所以宁愿回收慢也不愿意一直占用忘记回收。

    再看一个图:

    如下(( 这个图也说明了static为什么能全部引用,它在GC Root里))

    看完这个图,我们可以这样理解,我们jvm引擎一个线程或者其他在找GC Root相关联的,没有gcroot有关的就回收

    比如我们xxx.class对象,就是一种GCRoot,那么与xxx.class相关的什么方法啊变量啊也都能存活。反之就回收

    并且经过一次GC检测,分代年龄就会+1。而满了后又会右移,当对象分代年龄+到15,就会到lao老年代

    如果弄一个死循环也一直new对象,也在main里面又无法脱离GCRoot会怎样,就是不会回收对吧,就会一直不被检测回收但又

    一直new就会不停产生到堆里面然后检测+1然后右移然后进入老年代如图,而且还是一个动态的过程

     很多时候JAVA虚拟机因为full gc ,minor gc等产生STW(就是停止一切线程然后清理一下)这时客户感觉就是卡死了几秒然后就恢复了,因为STW也不是很特别慢,应该说是full gc慢一点minor gc是比较快的。

     这时候就引出调优------------就是减少STW产生次数

    第一就是full gc减少STW

    比如这个案例,产生60m大小的内存即New对象,可以是一个动作new 下单啊或者其他什么之类,抢东西new buy啊,注册啊,反正new的空间,

    很快eden800m是不是就满了大概13秒13X60=780,这时候会回收minor gc对吧,但是回收的此时此刻还有对象进来怎么办,不能放eden了,这时根据规则就放S0这些

    但是我们发现这里面因为s0太小,(超过一半内存的大对象理论)所以就会直接放进老年代。不停不停的到老年代不就产生最不喜欢的full gc(STW)

     所以

    我们需要怎样调优:把老年代调小

     这样之后我们发现好处一:minor的次数变少了,时间也变久了,因为根据原理比如下单,下一秒这个下单对象是不是就可能是一个变垃圾了直接就干掉了都不用检测加入S0 s1老年代等

                                  好处二就是:会发现这是一个eden和s0 s1的循环,根本不会进入老年代

    调优完毕

      

  • 相关阅读:
    SaltStack
    python模块相关
    python optparse命令解析模块
    python ConfigParser模块 配置文件解析
    pssh 批量管理执行
    rsync+inotify 实现实时同步
    [译]17-spring基于java代码的配置元数据
    [译]16-spring基于注解的配置元数据
    [译]15-spring 自动装配
    [译]14-spring 集合元素的注入
  • 原文地址:https://www.cnblogs.com/yangj-Blog/p/12956247.html
Copyright © 2011-2022 走看看