JVM-2-类加载子系统
概述
完整图如下
如果自己想手写一个Java虚拟机的话,主要考虑哪些结构呢?
类加载器
执行引擎
类加载器子系统作用类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。
ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。
加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)
class file存在于本地硬盘上,可以理解为设计师画在纸上的模板,而最终这个模板在执行的时候是要加载到JVM当中来根据这个文件实例化出n个一模一样的实例。
class file加载到JVM中,被称为DNA元数据模板,放在方法区。
在.class文件->JVM->最终成为元数据模板,此过程就要一个运输工具(类装载器Class Loader),扮演一个快递员的角色。
类的加载过程例如下面的一段简单的代码
12345public class HelloLo ...
JVM-1-JVM与Java体系结构
前言作为Java工程师的你曾被伤害过吗?你是否也遇到过这些问题?
运行着的线上系统突然卡死,系统无法访问,甚至直接OOMM!
想解决线上JVM GC问题,但却无从下手。
新项目上线,对各种JVM参数设置一脸茫然,直接默认吧然后就JJ了
每次面试之前都要重新背一遍JVM的一些原理概念性的东西,然而面试官却经常问你在实际项目中如何调优VM参数,如何解决GC、OOM等问题,一脸懵逼。
大部分Java开发人员,除会在项目中使用到与Java平台相关的各种高精尖技术,对于Java技术的核心Java虚拟机了解甚少。
一些有一定工作经验的开发人员,打心眼儿里觉得SSM、微服务等上层技术才是重点,基础技术并不重要,这其实是一种本末倒置的“病态”。如果我们把核心类库的API比做数学公式的话,那么Java虚拟机的知识就好比公式的推导过程。
计算机系统体系对我们来说越来越远,在不了解底层实现方式的前提下,通过高级语言很容易编写程序代码。但事实上计算机并不认识高级语言
架构师每天都在思考什么?
应该如何让我的系统更快?
如何避免系统出现瓶颈?
知乎上有条帖子:应该如何看招聘信息,直通年薪50万+? ...
Collections工具类的使用
1.作用操作Collection和Map的工具类
2.常用方法
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容 ...
Map接口
1.常用实现类结构
|—-Map:双列数据,存储key-value对的数据 —类似于高中的函数:y = f(x)
|—-HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
|—-LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。对于频繁的遍历操作,此类执行效率高于HashMap。
|—-TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序,底层使用红黑树
|—-Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
|—-Properties:常用来处理配置文件。key和value都是String类型
HashMap的底层:
数组+链表 (jdk7及之前)
数组+链表+红黑树 (jdk 8)
2.存储结构的理解
Map中的key:无序的、不可重复的,使用Set存储所的key —> key ...
Collection子接口:Set接口
1. 存储的数据特点无序的、不可重复的元素
具体的,以HashSet为例说明:
无序性:不等于随机性。存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的。
不可重复性:保证添加的元素照equals()判断时,不能返回true.即:相同的元素只能添加一个。
2. 元素添加过程(以HashSet为例)我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置,判断数组此位置上是否已经元素:
如果此位置上没其他元素,则元素a添加成功。 —>情况1
如果此位置上有其他元素b(或以链表形式存在的多个元素,则比较元素a与元素b的hash值:
如果hash值不相同,则元素a添加成功。—>情况2
如果hash值相同,进而需要调用元素a所在类的equals()方法: equals()返回true,元素a添加失败 equals()返回false,则元素a添加成功。—>情况3
对于添加成功的情况2和情况 ...
Collection子接口:List接口
1. 存储的数据特点存储有序的、可重复的数据。
2. 常用方法:(记住)增:add(Object obj)
删:remove(int index) / remove(Object obj)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
长度:size()
遍历:
① Iterator迭代器方式
② 增强for循环
③ 普通的循环
3. 常用实现类
|—-List接口:存储序的、可重复的数据。 –>“动态”数组,替换原的数组* |—-ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储* |—-LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储* |—-Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储
4. 源码分析(难点)4.1 ArrayList的源码分析
jdk 7情况 ...
Iterator接口与foreach循环
1.遍历Collection的两种方式:① 使用迭代器Iterator ② foreach循环(或增强for循环)
2.java.utils包下定义的迭代器接口:Iterator2.1说明:
Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。
2.2作用遍历集合Collectiton元素
2.3如何获取实例coll.iterator()返回一个迭代器实例
2.4遍历的代码实现123456Iterator iterator = coll.iterator();//hasNext():判断是否还下一个元素while(iterator.hasNext()){ //next():①指针下移 ②将下移以后集合位置上的元素返回 System.out.println(iterator.next());}
2.5图示说明
2.6 remove()的使用12345678 ...
Collection接口
1.单列集合框架结构
|—-Collection接口:单列集合,用来存储一个一个的对象
|—-List接口:存储序的、可重复的数据。–>“动态”数组
|—-ArrayList、LinkedList、Vector
|—-Set接口:存储无序的、不可重复的数据 –>高中讲的“集合”
|—-HashSet、LinkedHashSet、TreeSet
对应图示:
2.Collection接口常用方法:add(Object obj)
addAll(Collection coll)
size()
isEmpty()
clear()
contains(Object obj)
containsAll(Collection coll)
remove(Object obj)
removeAll(Collection coll)
retainsAll(Collection coll)
equals(Object obj)
hasCode()
toArray()
iterator()
3.Collection集合与数组间的转换123456789101112131415/ ...
Optional类的使用
java.util.Optional类
1.理解:为了解决java中的空指针问题而生!Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。
2.常用方法:1234567891011121314151617181920212223242526272829303132333435363738394041@Test public void test1(){ //empty():创建的Optional对象内部的value = null Optional<Object> op1 = Optional.empty(); if(!op1.isPresent()){//Optional封装的数据是否包含数据 System.out.println("数据为空"); ...
Stream API
1.Stream API的理解
Stream关注的是对数据的运算,与CPU打交道
集合关注的是数据的存储,与内存打交道
java8提供了一套api,使用这套api可以对内存中的数据进行过滤、排序、映射、归约等操作。类似于sql对数据库中表的相关操作。
2.注意点
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。(未执行终止操作前,中间的操作都不执行;执行终止操作时,前面的操作才一起执行)
3.Stream的使用流程
① Stream的实例化
② 一系列的中间操作(过滤、映射、…)
③ 终止操作
4.使用流程的注意点:
一个中间操作链,对数据源的数据进行处理
一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用(故,如果后面还需使用stream,需要重新生成)
5.步骤一:Stream实例化12345678910111213141516171819202122232425262728293031323334353637383 ...