01 软件的基础原理
01丨程序运行原理:程序是如何运行又是如何崩溃的?
- 程序: 静态的代码,无论是为文本格式还是可执行格式,想让程序处理数据、完成计算人物,必须把程序从外部设备加载到内存中,并在操作系统的管理调度下交给CPU执行
- 进程: 运行中的程序,包含可执行代码、和进程在运行期使用的内存堆空间、栈空间、供操作系统管理用的数据结构
- cpu分时共享技术进行并发操作,进程切换效率不高,所以有了线程切换
- 堆: 一块无序的内存空间,进程需要申请的内存,都会从堆空间中分配,分配到的内存地址则记录在栈中
- 栈: 一个后进先出的数据结构,由操作系统维护,主要用于记录函数内部的局部变量、堆空间分配的内存空间地址等
- 栈帧(stack frame): 用于保存正在执行的函数参数、局部变量、申请的内存地址等,栈帧之间互相隔离,不同函数定义的相同变量不会互相影响
- 进程的生命周期:
- 运行:进程在CPU上运行时,处于运行状态的进程数目 >= CPU的数目
- 就绪: 进程获得除CPU以外的所有所需资源,只要得到CPU即可运行,也称为等待运行状态
- 也称为等待或睡眠状态,进程正在等待某一事件发生(等待I/O完成、等待锁...)而暂时停止运行,此时即使进程分配到CPU也无法运行,此时进程处于阻塞状态
- Java web 应用运行时的主要结构(架构过程视图)
- 线程安全问题: 多个线程同时对一个堆中的数据执行操作,主要使用锁解决,锁会引起线程阻塞
- 线程阻塞可能是I/O,锁,网络请求,数据库链接获取等原因
02丨数据结构原理:Hash表的时间复杂度为什么是O(1)
- 数组: 最常用的数据结构,在内存中为一块连续的空间,数组中存放相同的数据类型
- 链表: 在内存中不连续存储,每个数据元素必须包含一个指向下一个数据元素的内存地址指针,查找数据只能通过遍历,因此查找复杂度为O(n),插入、删除简单,无需重新分配内存空间
- Hash表:
- Hash表的物理存储架构是一个数组,根据key计算出数组下标,就可以快速在数组中获取到所需的key和value,数组中不直接存储Key、Value数据,而是存储数据的地址指针
- 根据HashCode计算数组下标
- 栈: 添加了操作限制条件(后进先出,先进后出)的线性表,可以用数组、链表实现
- 队列: 添加了操作限制条件(先进先出)的线性表
- 树: 非线性表
03丨Java虚拟机原理:JVM为什么被称为机器(machine)
- JVM 的组成构造: JVM主要由类加载器、运行时数据区、执行引擎三个部分组成
- 运行时方法区: 主要包括方法区、堆、Java栈、程序计数寄存器
- 方法区主要存放从磁盘加载进来的类字节码,而在程序运行过程中创建的类实例则存放在堆里
- JVM封装了一组自定义的字节码指令集,有自己的程序计数器和执行引擎,像CPU一样可以执行运算指令。JVM还像操作系统一样有自己的程序装载和运行机制、内存管理机制、线程及栈管理机制,看起来就像一台完整的计算机,这就是JVM被称为machine(机器)的原因
- JVM的垃圾回收: 通过一种可达性分析算法(引用标记算法)识别垃圾对象
- JVM垃圾回收方法:
- 清理: 将垃圾对象占据的内存清理掉,将占用的内存空间标记为空闲,缺点是标记出来的空间不连续
- 压缩: 从堆空间的头部开始,将存活的对象拷贝放在一段连续的内存空间中,其余的空间就是连续的
- 复制: 将堆空间分为两部分,只在其中一部分创建对象,当这个部分空间用完时,将标记过的可用对象复制到另一个空间中
- 四种垃圾回收器:
- Serial串行垃圾回收器: 这是JVM早期的垃圾回收器,只有一个线程执行垃圾回收
- Parallel并行垃圾回收器: 启动多线程进行垃圾回收,如果JVM运行在多核CPU上,回收效率高于串行垃圾回收器,串行与并行垃圾回收器在垃圾回收线程工作时必须停止用户线程的工作,避免对象的引用标记错乱,这个过程被称为stop the world
- CMS并发垃圾回收器: 在垃圾回收的某些阶段,垃圾回收线程和用户线程可以并发运行,对用户线程影响较小,适用于Web应用
- G1垃圾回收器: 将整个堆空间分成多个子区域,各个子区域独自进行垃圾回收,回收过程中垃圾回收线程和用户线程并发运行
- JVM异常:
- OutOfMemoryError: 堆空间不足,可能是JVM分配的内存空间不足以让程序正常运行,也可能程序翠在内存泄漏
- StackOverflowError: 线程栈空间不足,通常因为方法调用的层次太多,导致栈帧太多
04丨网络编程原理:一个字符的互联网之旅
- 略
05丨文件系统原理:如何用1分钟遍历一个100TB的文件?
- inode文件控制块
- 分布式文件系统: 思路与RAID相似,对数据进行分片,同时像N台服务器进行数据写入,通过并行写入加快文件访问速度
- RAID: 独立硬盘冗余阵列,将多块硬盘通过硬件RAID卡或者软件RAID的方案管理起来,使其共同对外提供服务
- RAID5: 将数据分成N-1片,再利用这N-1片数据进行为运算,计算一片校验数据,然后将这N片数据写入N个硬盘,任何一块硬盘损坏时,都可以利用校验片的数据与其他数据进行计算得到这片丢失的数据
- Hadoop分布式文件系统HDFS架构设计
- 关键组件:
- DataNode: 负责文件数据的存储与读取操作
- NameNode: 负责整个分布式文件系统的元数据(MetaData)管理,即文件路径名、访问权限、数据块的ID以及存储位置等信息,相当于Linux系统中inode的角色。
- 高可用保障: 为了保证高可用,会将一个数据块复制为多份(缺省情况为3份)存储在不同的服务器上,当硬盘损坏、DataNode服务器宕机、交换机宕机等情况导致某数据块不能访问时,客户端会查找其备份的数据块进行访问
06丨数据库原理:为什么PrepareStatement性能更好更安全?
- 提交SQL语句的两种方式:
- 通过Statement直接提交SQL
- 通过PrepareStatement预编译SQL,然后设置可变参数再提交执行
- SQL执行过程:
- 语法分析器生成的抽象语法树不仅仅可以用来做语法检验,也是下一步处理的基础,语义分析和优化器会对抽象语法树进一步做语义优化,在保证SQL语义不变的前提下进行语义等价转换,使最后计算量和中间过程数据量尽可能小
- SQL语义分析和优化器就是要将各种复杂嵌套的SQL进行语义等就爱转化,得到有限几种关系代数计算结构,并利用索引等信息进一步进行优化,可以说是各个数据库最黑科技的优化部分
- 使用PrepareStatement的好处:
- 会预先提交带占位符的SQL到数据库进行预处理,提前生成执行计划,但给定占位符参数真正执行SQL时,执行引擎可以直接执行,效率更高
- 可以防止SQL注入攻击
- 应用程序对数据库连接的管理:
- 通过连接池进行管理,空闲连接会被及时释放
- 采用微服务架构,每个微服务连接各自对应的数据库,减少无关连接
- 数据库文件存储原理:
- 数据库索引使用B+树:
- 数据库的两种索引:
- 聚簇索引: 数据库记录和索引存储在一起,在叶子节点,索引和对应的记录行存储在一起,查找到索引就查找到了数据
- 非聚簇索引: 在叶子节点记录的不是数据行记录,而是聚簇索引,也就是主键。这种通过非聚簇索引查找到主键索引,再根据主键索引查找到行记录的过程,被称为回表
- 索引可以提高查询性能,但是存在维护成本,比如空间占用、插入修改的性能影响等
- 数据库索引使用B+树:
07丨编程语言原理:面向对象编程是编程的终极形态吗?
- 略