了解 jvm+dalvik+art(1)

2 篇文章 0 订阅
2 篇文章 0 订阅

简单了解一下,java 运行环境的基础是JVM,android的运行环境有dalvik和art。

  1. jvm
  2. delvik
  3. art
  4. 之间的区别和联系

jvm运行时数据区

程序计数器: 线程私有的,记录程序正在执行的虚拟机字节码指令的地址。理解为记录程序执行的位置。可以确保线程切换后能恢复到正确的执行位置。(单核cpu实现多线程是由快速切换线程执行来实现多线程同步执行的)
虚拟机栈: 线程私有的,描述java方法执行的内存模型,每个方法在执行时都会创建一个栈帧用于存储局部变量表、操作数帧、动态链接、方法出口等信息。每一个方法从调用只结束就对应着一个栈帧从入栈到出栈的过程。局部变量表存放编译期可知的各种基本数据类型,对象引用和returnAddress(指向一条字节码指令地址)
本地方法栈: 线程私有的,区别于虚拟机栈是为执行java方法的,本地方法栈是为执行native方法服务的。
方法区: 线程共享,存储已被加载的类信息,常量,静态变量,及时编译器编译后的代码数据。回收目标主要是常量池回收,类卸载。 内存划分为永久代
线程共享,主要是存放对象实例和数组。java程序最主要的内存工作区域。内存区域又划分为 新生代+老年代 ,新生代又划分为 eden + survivor1+survivor2

gc 垃圾回收

垃圾收集算法
  1. 引用计数法:为对象添加一个计数器,每当一个地方引用该对象时计数器+1,当引用失效时-1,当计数为0时认为该对象不再被引用,可以进行回收。此算法缺陷是无法解决对象循环引用问题。主流虚拟机都没有选用此算法。
  2. 标记清除法:利用根搜索算法对存活的对象进行标记,标记完毕后扫描未被标记的对象进行清除(回收)。此算法的缺点是容易造成内存碎片化严重。
  3. 复制算法:为了解决标记清除算法的缺陷,复制算法被提出来,将内存区域分为两块,只使用其中一块。当一块区域不足时,对本块内的可回收单位进行回收,并将存活的对象复制到另外一块区域中。这里有个明显的缺点就是对内存的大小要求比较高,因为只能使用1/2。
  4. 标记整理算法:为了解决复制算法的问题,该算法标记阶段和标记清除算法一样(利用根搜索算法进行标记存活对象)但是在清除时清除掉未被标记的对象的时候,将存活的对象进行向左移动。既解决了标记清除的碎片化问题,也解决了复制算法的空间浪费问题。
分代收集算法
  1. 新生代:年轻代主要以复制算法为主,年轻代对象生命周期短,回收频率比较高,所以采用较快的算法进行回收。
    新生代分为3个区域: eden+suvivor0+suvivor1 。大部分对象生成时是在eden区域(特殊情况:大对象数据–需要大量连续的内存空间,会直接进入老年代)。1)eden区域不足时将存活对象复制到suvivor0区域;2)eden区域再次不足时,将eden区域和suvivor0区域存活对象复制到suvivor1区域;3)重复多次1-2步骤后会将符合条件的对象复制到老年代。
  2. 老年代:老年代回收算法主要以标记整理算法。
  3. 持久代:永久代主要存放静态文件:java类和方法等。方法区回收主要是废弃常量和回收无用的类。对于无用的类判断需要满足3个条件:1)该类所有的实例已经被回收,堆中不存在该类的任何实例;2)加载该类的classloader已经被回收;3)该类的class对象没有在任何地方被引用。
分代收集器

Serial 串行收集器
ParNew 并行收集器
CMS 收集器
G1 收集器(分区收集器):G1将整个java堆划分为多个region区域,每个区域都可能是 年轻代和老年代。

类加载

类加载过程
JVM会严格按照这个过程来完成类的加载

触发类加载条件
  1. new getstatic putstatic invokestatic四条指令触发时类没有被加载,就立即触发类的初始化;
    1)new 指令就是代码中新创建一个对象
    2)getstatic putstatic 指令是操作类的静态属性
    3)invokestatic 指令对应的是操作类的静态方法
  2. 使用 java.lang.reflect包的方法对类进行反射调用时,类没有初始化,触发类的初始化;
  3. 初始化一个类时其父类没有初始化,会先对父类进行初始化
  4. 运行一个jvm必须制定一个包含main方法的类,会首先对其进行初始化;
  5. 使用jdk1.7动态语言支持时,MethodHandle 解析结果为REF_getstatic REF_putstatic REF_invokestatic时类没有初始化时,立即触发初始化
类加载过程

总的加载过程为:加载>>验证>>准备>>解析>>初始化>>使用>>卸载

  1. 加载:
    1)通过类的全限定名获取类文件字节流。获取方式有jar、war、网络获取、jsp文件生成。
    2)将二进制字节流静态类文件转化为运行时数据结构,这里只做数据结构转化,并未合并数据
    3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口,这个比较特殊,虽然为对象,但是存在在方法区。
  2. 验证:
    验证被加载的类是否有正确的结构,是否符合虚拟机对类的要求。确保虚拟机安全。
  3. 准备:为类变量分配内存并给默认值(初始化阶段才会给赋值具体值)
  4. 解析:将符号引用转换为直接引用
  5. 初始化:
    如果类中有静态块先执行类中静态块代码,然后执行java类中构造器的方法,并给类变量进行赋值。
  6. 使用
  7. 卸载
类加载器(双亲委派模型)

双亲委派:如果一个类加载器收到加载请求不会立即自己执行类的加载,而是把这个加载请求委派到父的类加载器,每一层加载器都是如此,所以所有的类加载请求都会委派到bootstrapclassloader 只有父类加载器反馈自己无法加载这个请求,子类加载器才会尝试对类执行加载。注意这里并不是直接的继承关系,只是一种逻辑关系。
bootstrap classloader 加载 lib 下或被 -Xbootclasspath 路径下的类
extension classloader加载lib/ext/下类文件
application classloader 加载用户目录下制定的文件

优势:
1)安全:防止恶意修改java核心类库(java.lang.*)类文件;
2)避免重复加载,当父加载器加载过后子加载器就不用再加载了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多一毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值