一、java语言

1.1 支持面向对象编程oop

强调支持,因为java同样可以面向过程编程。

oop的三大特性是:封装、继承、多态。

封装主要针对成员变量而言,oop的思想要求成员变量均为私有,不应该对外能够访问,一个符合oop思想的类应该只有公共方法对外能够访问;

继承,主要理解继承体系,private、protected、public在继承中的使用场景。理解java是单继承多实现的(与C++的区别);

多态主要指一个类的实例是运行时决定的,而不是声明时决定的。父类 a = new 子类();是可以的。这种作用在于可以面向抽象编程、面向接口编程,对象不必必须和声明的类一致,只要是它的子类、孙子类等即可;

1.2 jdk版本对java语言的改进

1996年发布jdk1.0,java语言具备基础的oop语法;

1997年发布jdk1.1,引入内部类;

2004年发布jdk1.5,引入语法糖,自动拆装箱、泛型、动态注解、枚举、可变长参数、遍历循环(foreach);

2014年发布jdk8,引入Lambda表达式;

二、jvm虚拟机(本文特指官方默认的HotSpot虚拟机)

2.1 发展

由一家小公司Longview Technologies开发出来,1997年被sun公司收购,jdk1.3之后正式成为官方默认虚拟机;

HotSpot得名来自于其热点代码探测技术,可以有效的把热点代码探测出来,并利用JIT编译器将热点代码进一步优化并编译成机器代码,提高运行效率;

2.2 jvm虚拟机的内存区域组成

程序计数器,线程私有,指向字节码指令;

java虚拟机栈,线程私有,主要就是描述java方法的,配合程序计数器一起一步一步往下执行方法(理解为什么是栈);

本地方法栈,线程私有,跟java虚拟机栈类似,区别是它用来执行非java方法;

java堆,线程共享,这是最大的一块虚拟机内存区域,主要就是我们new的对象都会分配在这里,这里分为新生代(Eden、Survivor1、Survivor2)和老年代;

方法区,线程共享,在HotSpot里叫永久代(Permanent Generation),存放加载的类信息、常量、静态变量等,static代码块、static变量、static方法都会存放在这里有一个副本。为什么叫永久代,主要是对这部分的对象实例回收的效率不高,这部分对象实例存活率较高;

运行时常量池,是方法区的一部分;

直接内存,不是虚拟机内存的一部分,指申请虚拟机内存外的内存。

2.3 垃圾收集算法

怎么样判断对象可以回收?有引用计数算法和可达性分析算法。引用计数算法很简单,给每个对象一个引用计数器,每当有一个地方引用了它,那么就给它计数器+1,当这个引用失效之后计数器-1,这样做非常高效,但有一个缺陷是互相引用的对象,无法被回收,造成内存泄露。HotSpot使用可达性分析算法,可达性分析算法从GC Roots对象是否可达来判断对象是否可以回收,GC Roots对象包括虚拟机栈引用的对象、方法区类静态属性引用的对象、方法区常量引用的对象、本地方法栈中引用的对象;

IBM研究指出98%的对象都是朝生夕死,故新生代中回收频率要较高,每次可以回收大量内存,老年代中经过两次以上的回收仍存活,说明回收的效率不高,回收频率可以低一点。另外,大对象不在新生代中分配,而是直接进入老年代。

①标记-清除算法。算法的思想是首先把需要回收的对象标注出来,然后统一清除回收。实现起来很简单,但标记和清除的效率不高,还会产生大量不连续的内存空间,影响后续为新对象分配内存,尤其是大对象。

②复制算法。针对标记-清除算法的问题,复制算法的思想是把内存区域均等的分成两块,比如10M的内存均等分为两块5M,每个时刻只能使用一块,先从第一块标记仍存活对象的对象,然后统一复制到第二块内存中,并按内存空间顺序排好,第一块内存则全部回收。第二次回收时就先从第二块开始,循环往复。这样做效率很高,并且内存空间可以连续分配。但造成一个问题是本来10M的内存只能用一半,造成内存的浪费。

HotSpot在实际实现复制算法时,将内存空间划分为Eden和两个Survivor,且默认Eden和Survivor的比例是8:1:1,新对象分配在Eden中,第一次回收后存活对象被复制到Survivor 1中,Eden全部清除,第二次新对象仍分配在Eden中,第二次回收时Eden和Survivor 1中存活对象被复制到Survivor 2中,Eden和Survivor 1全部清除。

这里有一个问题:如果存活对象超过内存的10%怎么办?这时候就需要从老年代中进行分配担保(Handle Promotion)。

③标记-整理算法。和新生代不同,在老年代中GC回收的效率不会太高,使用复制算法Survivor空间很可能是不够的,如果将Survivor调大又浪费内存空间,这时就提出了标记-整理算法应对老年代的实际情况。标记-整理算法内存回收时先将所有存活对象标记出来,但不进行清除,而是将存活对象都往内存的一端移动,那么内存末端都是可回收的对象,当这些可回收对象被“挤出”内存边界的时候,则被清除了。

由于HotSpot中把java堆中分为新生代、老年代,他们存活的几率不一样,所以按新生代和老年代采取不同的算法,这就叫分代收集算法,在新生代中采取复制算法,在老年代中使用标记-清除或标记-整理算法。

2.4 垃圾收集器

上面分析了新生代、老年代应该采取怎样的算法,HotSpot中针对实际应用场景,实现了不同的垃圾收集器;

①Serial收集器,复制算法,单线程,Client模式下默认新生代收集器。会有Stop The World问题;

②ParNew收集器,复制算法,多线程,新生代收集器;

③Parallel Scavenge收集器,复制算法,多线程,新生代收集器,与ParNew的区别在于它针对吞吐量设计的;

④Serial Old收集器,标记-整理算法,单线程,Client模式下默认老年代收集器;

⑤CMS收集器,标记-清除算法,多线程,老年代收集器,以降低停顿时间为目标,只在初始标记、重新标记的时候需要Stop The World,采取并发标记和并发清除降低停顿时间;

⑥G1收集器,标记-整理算法+复制算法,多线程,老年代收集器;

三、编译与运行

3.1 javac编译器编译

第一次编译,将.java文件编译成中间语言,输出.Class文件,这期间主要完成语法分析和词法分析(编译原理)、注解处理、语义分析(解语法糖等)、生成字节码Class文件;

3.2 解释器

类加载进解释器运行,类加载的过程有:加载、验证、准备、解析、初始化;

3.3 JIT即时编译器

解释器监控热点代码为JIT编译器进一步编译提供监控数据,触发JIT编译器将热点代码编译成机器代码;

本人知识水平有限,文章难免有纰漏之处,请不吝纠正勘误。

java语言与jvm虚拟机简介的更多相关文章

  1. 深入理解java:1. JVM虚拟机的构成

    1.JVM虚拟机的构成 什么是Java虚拟机? 作为一个Java程序员,我们每天都在写Java代码,我们写的代码都是在一个叫做Java虚拟机的东西上执行的. 但是如果要问什么是虚拟机,恐怕很多人就会模 ...

  2. java语言体系的技术简介之JSP、Servlet、JDBC、JavaBean(Application)

    转自:https://zhangkunnan.iteye.com/blog/2040462 前言 Java语言 Java语言体系比较庞大,包括多个模块.从WEB项目应用角度讲有JSP.Servlet. ...

  3. 【Java杂货铺】JVM#虚拟机加载机制

    代码编译的结果从本地机器码变为字节码,是储存格式发展的一小步,却是编程语言发展的一大步--<深入理解Java虚拟机> 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转化 ...

  4. Java语言与JVM中的Lambda表达式全解

    Lambda表达式是自Java SE 5引入泛型以来最重大的Java语言新特性,本文是2012年度最后一期Java Magazine中的一篇文章,它介绍了Lamdba的设计初衷,应用场景与基本语法. ...

  5. 探索Java语言与JVM中的Lambda表达式

    Lambda表达式是自Java SE 5引入泛型以来最重大的Java语言新特性,本文是2012年度最后一期Java Magazine中的一篇文章,它介绍了Lamdba的设计初衷,应用场景与基本语法.( ...

  6. Java 如何得到 JVM 虚拟机的 System Properties

    Java 6 jps 命令得到进程号 jinfo -sysprops <PID> > sysprops.txt 打开 sysprops.txt 就可以查找 Language Time ...

  7. Java语言学习day01--6月28日

    Java语言学习day01一:Java概述 1.Java语言发展史 任职于太阳微系统的 詹姆斯·高斯林 等人于1990年代初开发Java语言的雏形,最初被命名为 Oak ,目标设置在 家用电器等小型系 ...

  8. [零] Java 语言运行原理 JVM原理浅析 入门了解简介 Java语言组成部分 javap命令使用

    Java Virtual Machine  官方介绍 Java虚拟机规范官方文档 https://docs.oracle.com/javase/specs/index.html 其中以java8的为 ...

  9. Java语言简介、基础组成、封装、继承、多态、抽象类、内部类、接口

    目录 Java简介 Java语言基础组成 面向对象 对象 封装 构造函数 this关键字 static(静态关键字) 主函数 静态什么时候用呢? 面向对象(数组工具对象建立) 设计模式 继承 成员变量 ...

随机推荐

  1. Win10 部署 依赖 NET3.5 项目,报错 无法安装 NET3.5 ,该如何解决?

    下载 NetFx3.cab Cab 安装包 拷贝 NetFx3.cab 文件至 C:\Windows 目录 打开命令行窗口(管理员权限) 输入以下内容: dism /online /Enable-Fe ...

  2. 初版python计算器

    作业: 使用正则表达式实现计算器功能. 实现: 1.实现带括号的计算 2.实现指数.加减乘除求余等功能 先看运行结果: 请输入您的计算式: 1 - 2 * ( (60-30 +(-40.0/5) * ...

  3. 【java学习笔记】序列化、反序列化

    序列化 是将对象的完整信息保存起来的过程(持久化).    序列化流:ObjectOutputStream 反序列化 是将对象进行还原的过程(反持久化).               反序列化流:Ob ...

  4. jQuery提示parsererror错误解决办法

    jquery来处理ajax,用到了json.但是很诧异,jquery的ajax回调时一直调用了error函数(一直提示parsererror异常),success函数一次没执行过 $.ajax({ t ...

  5. 【mongodb系统学习之十】mongodb查询(二)

    5).常用查询条件: a).比较操作符:"$lt","$lte","$gt","$gte",分别是<,<=, ...

  6. C#利用 string.Join 泛型集合快速转换拼接字符串

    C#利用 string.Join 泛型集合快速转换拼接字符串 List<int> superior_list = new List<int>(); superior_list. ...

  7. CSS的继承性与优先级

    一.CSS的继承性 在CSS中不可继承的属性:display.margin.padding.border.background.width.min-width.max-width.height.min ...

  8. java 后台封装json数据学习总结(一)

    一.数据封装 1. List集合转换成json代码 List list = new ArrayList(); list.add( "first" ); list.add( &quo ...

  9. StackExchange.Redis 二次封装

    在NuGet直接搜索StackExchange.Redis,下载引用包: 帮助类: public class RedisUtils { /// <summary> /// redis配置文 ...

  10. hdu5923 Prediction

    jxt的思路 先膜一发 先处理 T这棵树上每个点到祖先这条链的点所生成的并查集 每个点的并查集都得分开来存 这个dfs做就好了 最后询问的时候 将k 个点的并查集合并就是这个询问的连通图 易得答案 # ...