谈谈对java平台的理解和java到底是不是解释执行

谈谈对java平台的理解和java到底是不是解释执行

前言

前几天看到了一个面试题问谈谈对java平台的理解和Java是解释执行吗?
第一眼看到这个问题,第一感觉是自己会,自己天天和java亲密接触怎么会答不出来呢?但要回答这个问题,一时之间又不知道该怎么说,不知道从何说起,也不知道怎么全面的说清楚,经过努力研究写下这篇文章,算是对自己一个考察.(最后有总结如果觉得讲的啰嗦可以直接看最后面总结)

本人辛苦所写,不对的地方欢迎批评,希望尊重劳动成果,如需转载,请标明原文链接和作者

谈谈对Java的理解

如果让你谈谈java,你可能会第一时间就说出java 是跨平台的语言,可以实现一次编译,到处运行(Write once, run anywhere),还可能你还会说出,java自带一个垃圾收集器(Garbage, Colletion),它会帮助程序员回收分配的内存,大部分情况下,程序员不需要操心内存分配和回收.但总觉的这些说法太过于笼统,有点像背书一样.到底对java了解到什么程度,今天停下来总结一下.

在我们刚开始学习java的时候都会懵逼的去安装一个jdk,jdk是java的核心,接下来我会围绕jdk谈谈我对Java的理解,首先,安装jdk的时候他会问你是否会安装单独的jre,一般我们都会选择是,我是把jdk和独立安装的jre分开的,但jdk自己里面也会一套自己的jre,java 运行会先找当前目录下的虚拟机,也就是用的jdk的虚拟机,废话不多说上图.
在这里插入图片描述
在这里插入图片描述
这俩个jre是一样的,jre是java最小运行环境,jdk是java最小开发环境,jdk是包含jre的,但比jre多了java更多的工具,比如java编译器和一些java调试的工具,如果你只是像运行java代码,那么有jre就够了,如果你想自己编写java代码,那你就需要jdk了,但为什么要在安装一个独立的jre,具体原因我就不清楚了(难道是单纯的介绍俩者的区别吗?)当配置好java 的环境变量后,可以在doc界面通过java -version 命令来查看自己java的版本信息,

在这里插入图片描述

第一行可以得知我的Java版本是1.8的,我们重点看一下第二行和第三行,之前一直再说jre,接下来就解释一下jre,层层递进.
补充一下, java 有俩种运行模式, 一种server 还有一种client,通常我们都用的server,
client 是用来写桌面级应用程序的,
jre是java 运行环境,它主要包括jvm和java核心类库

jvm是java 虚拟机(Java Virtual Machine)它是用来运行.class文件,当java代码写好后通过Java编译器编译后, .java文件变成.class文件,而jvm就是用来加载编译后的.class文件,为什么java可以跨平台,原因就在这! jvm相当于java代码和操作系统中间的翻译官,jvm可以让我们不去关心操作系统的差异,它负责把字节码文件也就是.class文件翻译成计算机只认识的机器码,java对不同操作系统都提供了对应的jdk,也就是java对不同的操作系统都提供对应的jvm,所以你在windows编译好的字节码文件,拿到linux操作系统上照样可以执行,当然前提你的linux操作系统安装了jre,

jvm还有一个重要的地方就是它提供了java垃圾回收器(Garbage Collection),它可以帮助程序员回收分配的内存,多数情况下,可以让程序员专心自己的功能实现,不用去考虑内存问题,

Garbage Collection 简称 GC 它又涉及到 java运行时的内存划分,jvm在运行java 代码时候把内存划分成 堆区,栈区,方法区,程序计数器,它主要回收堆区,对象实体分配在堆区,堆区也是最大的内存区域,所以它的内存分配至关重要,垃圾回收器主要就帮你管理这块内存,我粗略的说一下回收过程,具体细节大家可以看其他大牛的博客,首先它要解决什么对象应该被回收, 这里有俩种策略,一种叫做引用计数法,每当一个对象实体被引用计数器就加一,取消引用计数器就减一,这种方法实现简单,但有一个致命缺点,就是它不能解决环引用, 另外一种策略就是可达性分析,就是从根对象对象可以不可以找到一条路径到达当前对象实体,如果可以就不会被回收,如果找不到就会被回收,目前jvm用的就是这种方法判断对象是不是该被回收,下面四种类型对象可以作为根对象

  • 虚拟机栈中引用的对象
  • 方法区中类静态变量引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中引用的对象

解决了什么对象可以被回收后,再谈谈垃圾回收算法,1.标记-清除算法,是最基础的算法,它分为俩个过程,首先在判断那些对象可以被回收后 就标记好被回收对象的内存区域,然后在开始清除掉被标记的内存,但有俩个缺点,标记 和清除过程的效率都不高,清楚后内存存在大量不连续空间,当一个大对象进来时找不到连续的空间分配,就会导致提前触发垃圾回收,

为了解决高效率问题,又出现了一种算法,复制算法,它把内存分为俩块, 每次只使用其中一块内存,当判断完哪些对象要被回收后,把不会被回收的对象转移到另一块,按顺序排好,然后直接清除之前使用的那块内存,内存分配时就不要在考虑内存碎片的情况了.
但这种算法代价昂贵,浪费掉一半内存.而且如果每次需要回收对象不多就要就行转移大量对象,效率也不高,

所以有人又提出了一种标记整理算法,它是标记清除算法的改良版,在标记完后,不着急清除,先把存活的对象移动到一边,移动完成后标记一下尾巴地方,然后把头到尾巴以外的内存区域清除掉,

针对对象存活时间不同的情况,最终jvm用了一种更好的策略,就是分代回收,它把堆区分为新生代和老年代俩种区域,比例1:2,新生代用来存放存活率不高的对象(通常朝生夕灭),老年代用来存放存活率很高的对象,这样根据新生代存活率不高的情况,采用复制算法,它把新生代又划分为 Eden 和 survior区域,比例为8:1,survior 又1:1划分成 survior from,和survior to,每次使用Eden 和 survior from 区域,也就是使用新生代百分之90 的区域,通常情况下,新生代存活率很低, 不会超过百分之10(万一超过了,有一种保护机制就是把放不下的对象直接扔到老年代里面去);所以当Minor GC 也就是新生代的垃圾回收时, 把存活的对象 放到 survior to 区 然后清空Eden 和survior from ,然后当需要给对象分配空间时 使用 survior to 和Eden区 保证 有百分之10 的 survior区时干净的,用来存放存活对象,这像一种轮流机制把, 只浪费百分之10 内存,效率提升很大,回收频繁,回收速度块,当minor GC 经历了15次还存活的对象就是老油条对象了,就要去属于它的地方,老年代,下面就介绍老年代的原理

老年代是用标记整理算法,当一个对象很大 新生代 分配不下,老年代也分配不下,就会触发 full GC ,当 老年代内存不足时候不够存放新生代要晋升过来的对象 也会触发 full GC 通常情况 发生full GC 会先minor GC一次 但不是绝对,由于full GC 很慢(其中有著名 stop the world) 所以 应该尽量避免full GC的发生,以上垃圾回收具体细节和涉及内容要比我讲述的远远复杂的多,感兴趣可以自己钻研一下

接下来还没有完!

jre 除了jvm 还有一个重要的组成 就是Java核心类库,这是构成Java运行环境的组成之一,其中核心类库源码我还没有来的及读,我列举一下重要的java类库(阅读顺序从上而下)

  • java.lang
  • java.util
  • java.util.concurrent
  • java.util.concurrent.atomic
  • java.lang.reflect
  • java.lang.annotation
  • java.util.concurrent.locks
  • java.io
  • java.nio
  • java.net

最后解释一下,java 到底是不是解释执行,我举一个例子简单说一下,编译执行和解释执行概念,编译执行就是把英文全部翻译好给你听,而解释执行就是同声翻译,英语一句我翻译一句,所以编译执行 就像C语言把代码翻译成机器码执行,效率很快,而解释执行 java 中 运行的可是字节码文件 计算机不认识啊, 所以 jvm 里面有一个解释器, 执行哪一行代码就翻译哪一行,但这样效率也太低了, 所以java就改进了,java 是通过 JIT (即时编译器) 把经常运行的代码作为"热点代码"编译与本地平台相关的机器码,并进行各种层次的优化
AOT编译器: Java 9提供的直接将所有代码编译成机器码执行
所以说java 是解释执行的不完全正确!

最后总结一下

Java特性:
面向对象(封装,继承,多态)
平台无关性(JVM运行.class文件)
语言(泛型,Lambda)//lambda 是匿名函数,java1.8新特性,这玩意我也不懂,
类库(集合,并发,网络,IO/NIO)
JRE(Java运行环境,JVM,类库)
JDK(Java开发工具,包括JRE,javac,诊断工具)
Java是解析运行吗?
不正确!
1,Java源代码经过Javac编译成.class文件
2,.class文件经JVM解析或编译运行。
(1)解析:.class文件经过JVM内嵌的解析器解析执行。
(2)编译:存在JIT编译器(Just In Time Compile 即时编译器)把经常运行的代码作为"热点
代码"编译与本地平台相关的机器码,并进行各种层次的优化。
(3)AOT编译器: Java 9提供的直接将所有代码编译成机器码执行。

,

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值