代理
动态代理和静态代理的区别代理是一种常用的设计模式,目的是:为其他对象提供一个代理以控制对某个对象的访问,将两个类的关系解耦。代理类和委托类都要实现相同的接口,因为代理真正调用的是委托类的方法。 区别: 静态代理:由程序员创建或者是由特定工具创建,在代码编译时就确定了被代理的类是一个静态代理。静态代理通常只代理一个类; 动态代理:在代码运行期间,运用反射机制动态创建生成。动态代理代理的是一个接口下的多个实现类。 实现动态代理的方式?Java动态代理是一种在运行时动态生成代理类的机制,用于代理其他对象的访问。与静态代理不同,动态代理无需事先定义代理类,而是在程序运行时根据指定的接口和处理器生成代理类。 Java动态代理主要分为两种类型: 基于接口的代理(JDK动态代理):...
GC类型划分
...
引用类型总结
无论是通过引用计数法判断对象引用数量,还是通过可达性分析法判断对象的引用链是否可达,判定对象的存活都与“引用”有关。 JDK1.2 之前,Java 中引用的定义很传统:如果 reference 类型的数据存储的数值代表的是另一块内存的起始地址,就称这块内存代表一个引用。 JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用、虚引用四种(引用强度逐渐减弱) 1.强引用(StrongReference)以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError...
垃圾收集器
本文参考文章: (七)JVM成神路之GC分代篇:分代GC器、CMS收集器及YoungGC、FullGC日志剖析引言 在《GC基础篇》中曾 - 掘金 (八)JVM成神路之GC分区篇:G1、ZGC、ShenandoahGC高性能收集器深入剖析引言 在《GC分代篇》中 - 掘金 在如今的官方JDK中,JVM的GC收集器具体实现存在十款,分别为Serial、ParNew、Parallel Scavenge、CMS、Serial Old(MSC)、Parallel Old、G1、ZGC、Shenandoah、Epsilon等,如下: 在上图中共有十款GC收集器,它们可以根据回收时的属性分为分代和分区两种类型: 分代收集器:Serial、ParNew、Parallel Scavenge、CMS、Serial Old(MSC)、Parallel...
死亡对象判断方法
堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断哪些对象已经死亡(即不能再被任何途径使用的对象) 1.引用计数法给对象中添加一个引用计数器: 每当有一个地方引用它,计数器就加 1; 当引用失效,计数器就减 1; 任何时候计数器为 0 的对象就是不可能再被使用的。 这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间循环引用的问题 2.可达性分析算法目前主流的商用JVM都是通过可达性分析来判断对象是否可以被回收的。 这个算法的基本思路是: 通过一系列被称为「GC Roots」的根对象作为起始节点集,从这些节点开始,通过引用关系向下搜寻,搜寻走过的路径称为「引用链」,如果某个对象到GC Roots没有任何引用链相连,就说明该对象不可达,即可以被回收。 要想理解可达性算法,首先要想明白几个问题: 1、什么是对象可达? 对象可达指的就是:双方存在直接或间接的引用关系。根可达或GC Roots可达就是指:对象到GC Roots存在直接或间接的引用关系。 2、GC...
JMM三大特性与原子操作、happens-before原则
JMM规范下三大特性在 Java 内存模型(JMM)规范下,有三大特性,分别是原子性、可见性和有序性。 一、原子性 概念:原子性是指一个操作或者一系列操作要么全部执行,要么全部不执行,不会被中断。在 Java...
垃圾收集算法
1.标记-清除算法标记-清除(Mark-and-Sweep)算法分为“标记(Mark)”和“清除(Sweep)”阶段:首先标记出所有不需要回收的对象,在标记完成后统一回收掉所有没有被标记的对象。 注:关于GC标记到底在哪儿?其实在上一章节中就已经分析过了,在对象头中存在一个markword字段,而GC标志位就存在其内部。 它是最基础的收集算法,后续的算法都是对其不足进行改进得到。这种垃圾收集算法会带来两个明显的问题: 内存碎片化问题:由于内存是连续的,所以在对象被删除之后,内存中会出现很多细小的可用内存碎片。如果我们需要的是一个比较大的空间,很有可能这些内存单元的大小过小无法进行分配。 分配速度慢:由于内存碎片的存在,需要维护一个空闲链表,极有可能发生每次需要遍历到链表的最后才能获得合适的内存空间。 关于具体是标记可回收对象还是不可回收对象,众说纷纭,两种说法其实都没问题,我个人更倾向于是前者。 如果按照前者的理解,整个标记-清除过程大致是这样的: 当一个对象被创建时,给一个标记位,假设为 0...
Java新特性
Java 8新特性Lambda表达式、接口的方法类型、Stream流、optional、方法引用、日期类、HashMap、元空间和永久代 1.Interfaceinterface 的设计初衷是面向抽象,提高扩展性。这也留有一点遗憾,Interface 修改的时候,实现它的类也必须跟着改。 为了解决接口的修改与现有的实现不兼容的问题。新 interface 的方法可以用default 或 static修饰,这样就可以有方法体,实现类也不必重写此方法。 一个 interface 中可以有多个方法被它们修饰,这 2 个修饰符的区别主要也是普通方法和静态方法的区别。 default修饰的方法,是普通实例方法,可以用this调用,可以被子类继承、重写。 static修饰的方法,使用上和一般类静态方法一样。但它不能被子类继承,只能用Interface调用。 2.Lambda 表达式接下来谈众所周知的 Lambda 表达式。它是推动 Java 8 发布的最重要新特性。是继泛型(Generics)和注解(Annotation)以来最大的变化。 使用 Lambda...
MySQL执行一条SQL语句的过程
从上图可以看出, MySQL 主要由下面几部分构成: 连接器: 身份认证和权限相关(登录 MySQL 的时候)。 查询缓存: 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。 分析器: 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。 优化器: 按照 MySQL 认为最优的方案去执行。 执行器: 执行语句,然后从存储引擎返回数据。 执行语句之前会先判断是否有权限,如果没有权限的话,就会报错。 插件式存储引擎:主要负责数据的存储和读取,采用的是插件式架构,支持 InnoDB、MyISAM、Memory...
volatile 关键字
volatile 关键字的作用在 Java 中,volatile关键字主要有以下作用: 一、保证可见性 当一个变量被声明为volatile时,它确保了不同线程对这个变量的修改是可见的。也就是说,当一个线程修改了一个volatile变量的值,其他线程能够立即看到这个变化。 例如,在没有使用volatile关键字的情况下,线程 A 对一个普通变量进行了修改,但是线程 B 可能不会立即看到这个修改,因为每个线程可能会将变量的值缓存到自己的本地内存中。而如果这个变量被声明为volatile,那么线程 A 的修改会立即被刷新到主内存中,并且线程 B 在读取这个变量时会从主内存中获取最新的值,而不是使用自己本地内存中的缓存值。 二、禁止指令重排序 在 Java...