当前位置: 首页 > news >正文

ai智能搜索引擎app排名优化

ai智能搜索引擎,app排名优化,wordpress wp_head函数,物流网站毕业论文文章目录 JVM简介JVM运行时数据区堆(线程共享)方法区/元空间/元数据区(线程共享)栈程序计数器 JVM类加载类加载过程双亲委派模型 垃圾回收机制(GC)判断对象是否为垃圾判断是否被引用指向 如何清理垃圾, 释放对象? JVM简介 JVM 是 Java Virtual Machine 的简称, 意为Java虚拟机…

文章目录

  • JVM简介
  • JVM运行时数据区
    • 堆(线程共享)
    • 方法区/元空间/元数据区(线程共享)
    • 程序计数器
  • JVM类加载
    • 类加载过程
    • 双亲委派模型
  • 垃圾回收机制(GC)
    • 判断对象是否为垃圾
      • 判断是否被引用指向
    • 如何清理垃圾, 释放对象?

JVM简介

JVM 是 Java Virtual Machine 的简称, 意为Java虚拟机.

虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。

JVM运行时数据区

也就是JVM的内存布局

在这里插入图片描述

堆(线程共享)

保存程序中创建的对象

方法区/元空间/元数据区(线程共享)

存放被JVM加载的类信息(类对象), 常量, 静态变量(static), 即时编译器编译后的代码等数据

存放方法的调用关系, 局部变量

程序计数器

记录了当前线程执行的下一条指令的内存地址


class Test {public int n = 20;public static int a = 10;
}
public class Main() {public static void main(String[] arg) {Test t = new Test();}
}

n是普通的成员变量, 就包含在new的对象的内部, 存放在堆上

a是一个静态成员变量, 包含在类对象中, 存放在方法区中

t是一个局部变量, 存放在栈上

new Test()这个对象是保存在堆上的

栈上的t保存了堆上的new Test()的内存地址

JVM类加载

Java程序一开始是一个.java文件, 通过javac编译成.class文件, 运行java程序, JVM就会读取.class文件, 把文件的内容加载到内存中, 并构造成一个.class对象

类加载就是: 把类从硬盘文件加载到内存中.

类加载过程

流程:

  1. 加载: 找到.class文件, 打开文件, 并读取文件内容, 并且尝试解析格式

  2. 验证: 检查当前.class文件是否符合标准格式

  3. 准备: 给类对象分配内存. 分配出来的内存空间, 内容就是全0的值.

  4. 解析: 将常量池内的符号引用替换为直接引用的过程, 也就是初始化常量的过程. 初始化类对象中涉及到的一些字符串常量, 这些字符串常量在.class文件中已经存在, 直接读到内存中就行.

    • 符号引用: 偏移量. 在.class文件中不知道字符串真实的内存地址在哪, 只知道一个相对的偏移量, 知道字符串的内容在.class文件的哪个地方.
    • 直接引用: 真实的内存地址
  5. 初始化: 对类对象进行更具体的初始化操作. 初始化金泰城园, 执行静态代码块, 加载父类…


双亲委派模型

实则单亲.

JVM加载.class文件的时候, 需要用到"类加载器"模块.

JVM中自带了三个类加载器:

  • Bootstrap ClassLoader: 负责加载标准库中的类
  • Extension ClassLoader(父亲是Bootstrap ClassLoader): 负责加载JVM扩展的库
  • Application ClassLoader(父亲是Extension ClassLoader): 负责加载第三方库.

不是父类子类的继承关系, 而是对象里有一个parent引用指向 父 类加载器 实例

当接收到类加载请求时:

  • Application ClassLoader是类加载的入口, 不会立即就搜索第三方库的目录, 而是先把任务委派给父亲, 让父亲先尝试加载.
  • 到了Extension ClassLoader, 也不会立即搜索扩展库的目录, 把任务委派给父亲, 让父亲先尝试加载.
  • 到了Bootstrap ClassLoader, 也不会立即搜索扩展库的目录, 把任务委派给父亲, 但是他没有父亲, 就只能自己来搜索了. 如果找到了这个类, 就会进行后续的加载流程; 如果没有, 那么任务就会交付给孩子来解决.
  • 如果任务回到了Extension ClassLoader, 他就要搜索扩展库的目录, 如果找到了这个类, 就会进行后续的加载流程; 如果没有, 那么任务就会交付给孩子来解决.
  • 如果任务回到了Application ClassLoader, 他就要搜索第三方库的目录, 如果找到了这个类, 就会进行后续的加载流程; 如果没有, 那么就抛出异常.

这样做的目的: 明确类的优先级(标准库的类最优先加载, 扩展库其次, 第三方库最低)

标准库中有一个类java.lang.String, 如果我们自己也写了一个java.lang.String类

JVM始终是加载标准库里的类, 而不会加载到我们写的类, 这样便可以避免程序员的代码对标准库的代码产生负面影响


类加载的时机?(类似于懒汉模式, 用到了才加载)

  1. 构造了这个类的实例
  2. 使用了该类的静态方法, 静态属性
  3. 子类的加载会触发父类加载.

垃圾回收机制(GC)

对于程序计数器, 栈而言, 它的生命周期与相关的线程有关, 随线程生, 随线程灭, 并且这两个区域的内存分配和回收具有确定性, 因为当方法或者线程结束了, 内存就自然跟着线程回收了. 所以垃圾回收主要是回收堆和方法区这两个区域.

缺点: 消耗额外的系统资源, 消耗一定的时间, 可能有STW问题

垃圾回收是以对象为单位进行回收

垃圾回收的流程分为两步: 1. 判定对象是否为垃圾. 2. 释放对象的内存

判断对象是否为垃圾

一个对象, 如果在后续代码中不会被继续使用到了, 就可以视作是垃圾了

  • 不会被继续使用: 没有被任何引用指向

    public void test() {T t = new T();t.func();
    }
    test();
    

    调用方法test的时候, 局部变量t被创建, 当test方法执行完了之后, t自然销毁, 此时new T()就没有被引用指向了, 这个对象也就是垃圾了.

判断是否被引用指向

  1. 引用计数

    给这个对象里面安排一个计数器, 每次有引用指向它, 就把计数器+1, 每次引用被销毁, 计数器-1, 当计数器为0, 意味着该对象就是垃圾了

    class Test {//
    }
    Test t = new Test();//new Test()里的计数器为1
    Test t2 = t;//new Test()里的计数器为2
    Test t3 = t2;//new Test()里的计数器为3
    t = null;//new Test()里的计数器为2
    t2 = null;//new Test()里的计数器为1
    t3 = null;//new Test()里的计数器为0, 此时该对象为垃圾了
    

    该方法并非是JVM中使用的方案, Python和PHP的虚拟机GC采用的是此方案

    缺陷:

    • 空间利用率低, 浪费更多的内存空间

    • 可能存在循环引用的问题, 导致对象不能正确识别为垃圾.

      class Test {public Test t;
      }
      Test a = new Test();//计数器为1
      Test b = new Test();//计数器为1
      a.t = b;//计数器为2
      b.t = a;//计数器为2
      a = null;//计数器为1
      b = null;//计数器为1
      

      在这里插入图片描述

      此时这两个对象的引用计数不为0, 不能被当做垃圾. 与此同时, 一想要使用对象1, 就需要访问对象2. 要想使用对象2, 就得先访问到对象1…这就是循环引用

  2. 可达性分析(JVM使用的方案)

    JVM首先会从现有代码中的能直接访问到的对象出发, 尝试便利所有能访问的对象, 只要对象能访问到, 就会标记成"可达", 完成整个遍历之后, 不可达的对象, 就相当于是垃圾了.

    这样的操作没有额外的空间开销, 但是消耗了更多的时间.

    那些是能直接访问到的对象呢?

    这些对象又被称为gc roots.

    1. 栈上的局部变量.
    2. 常量池里的引用
    3. 方法区中类静态属性引用的对象
    4. 本地方法栈中 JNI(Native方法)引用的对象

    代码执行过程中, 一个对象是否是垃圾, 往往是动态变化的(之前不是垃圾, 现在是垃圾了), 所以可达性分析的扫描是持续的周期性的

如何清理垃圾, 释放对象?

  1. 标记清除: 被标记为垃圾的对象直接清除.

    弊端: 申请内存的时候, 都是申请的连续的空间, 直接释放会导致内存的碎片化, 会破环原有的连续性, 可能会导致有内存, 但是申请不了.

  2. 复制算法: 通过冗余的内存空间, 把有效的对象复制到另一部分空间, 避免内存碎片.

    把一个内存分成两份, 一份使用, 一份等待有效对象被复制过来.

    弊端: 如果复制的对象多, 开销会很大, 而且内存利用率也不高, 相当于浪费了一般的内存.

  3. 标记整理: 类似于顺序表的删除元素操作.

    弊端: 这样的方式虽然解决了复制算法内存利用率低的问题, 但是搬运对象的成本也比较高.

  4. 分代回收: 采用分治的思想, 进行代的划分, 把不同生命周期的对象放在不同代上, 不同代上采用最适合它的垃圾回收方式进行回收.

    Java的对象大体分为两类: 1. 生命周期很长的; 2.生命周期很短的

    不同的对象的生命周期是不一样的. 因此, 不同生命周期的对象可以采取不同的收集方式, 以便提高回收效率.

    如何分代?

    JVM根据对象存活的周期(GC周期性扫描)不同, 把对内存划分了2块, 为新生代老年代.


    新生代又分为伊甸区(Eden)和幸存区(Survivor).

    伊甸区占大部分内存, 这里存储的对象生命周期都很短. 经过一次GC后, 存活下来的对象就会通过复制算法复制到幸存区.

    幸存区是两块大小相等的内存区域, 每次只用一块, 如果这里的对象经过GC后存货, 会继续被复制到另一块幸存区, 如此往复.如果一个对象在幸存区里经过了很多轮GC还存活, 证明它的生命周期很长, 那么它就会被复制到老年代.


    老年代的GC频率比新生代要低. 这里清理垃圾的策略是标记整理

    如果一个对象的体积很大, 那么他会直接进入老年代, 因为这样的对象不适合进行复制

http://www.mmbaike.com/news/106605.html

相关文章:

  • 由担路网提供网站建设app拉新放单平台
  • 软件开发与网站建设百度互联网营销顾问
  • wordpress+blog+推荐沈阳关键词优化报价
  • 做网站用那一种语言最好seo营销技巧培训班
  • 河北建设行业信息网站百度app 浏览器
  • b2b电子商务交易模式网站的特点广州线下培训机构停课
  • 网站备案政策百度账号登录个人中心
  • 微信公众交友网站开发快手流量推广网站
  • 网站icp备案号怎么查询淘宝运营培训机构
  • 广东省政府网站集约化建设seo诊断分析工具
  • 网站排名如何提升必应搜索引擎网址
  • 委托网络公司做的网站侵权百度搜索引擎收录
  • 广州一次做网站百度seo排名优化公司哪家强
  • 男女生做恶心的网站最近一周的新闻大事10条
  • 微商城网站建设方案郑州百度seo排名公司
  • 提供邢台企业做网站关键词优化工具互点
  • 网络营销跟做网站有什么区别网络推广是做什么工作
  • wordpress 限制文章苏州seo怎么做
  • vps的网站打不开宁波seo网站排名
  • 如何做外贸独立网站石家庄百度推广排名优化
  • 宁波网络营销服务上海抖音seo
  • 新余建站公司南京seo建站
  • 广州化妆品网站建设济南做网站公司哪家好
  • 佛山定制网站建设微营销软件
  • 兼职做ppt是哪个网站如何做市场调研和分析
  • 自助建站系统建的网站做排名吗怎么制作网页教程
  • wordpress 文章所属分类百度蜘蛛池自动收录seo
  • 网站开发预算成本价在百度怎么发布作品
  • 青羊区电商型网站建设设计百度账号登陆
  • wordpress添加搜索引擎seo网站有哪些