自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(134)
  • 收藏
  • 关注

原创 JVM修炼之路【12】- GC调优 、性能调优

上一篇中 我们详细讲了内存溢出 内存泄漏 还有相关的案例。这篇博客中我们主要了解一下GC调优。有些新手可能会有一点 疑问—— 这两者不是一回事吗??其实说一回事 也没错 因为GC调优本质上还是针对 堆上的内存只不过前面我们关注的侧重点在于 不合理的代码或者设计 会造成OOM 内存的不合适使用。这一篇我们侧重于 垃圾回收器 做各种gc动作对于系统的影响,还有垃圾回收器的参数设置。

2024-04-13 22:22:13 386

原创 JVM修炼之路【11】- 解决内存溢出、内存泄漏 以及相关案例

前面的10篇 都是基础的知识,包括类加载的过程 类加载的细节,jvm内存模型 垃圾回收 等等,这一篇我们开始实战了解一下 各种疑难杂症:怎么监控 怎么发现 怎么解决。

2024-04-12 23:58:44 583

原创 JVM修炼之路【10】- 垃圾回收器和垃圾回收算法

在 Minor GC 中,存活的对象会被移动到存活区域(Survivor Space),而不再被引用的对象将被标记为可回收的垃圾。被标记为垃圾的对象将被回收释放。在 Full GC 中,所有的存活对象都会被标记并移动,而不再被引用的对象将被回收释放。我们之前说了GC root 根节点 可达性分析法 ,去寻找那些有根的对象 和断根的对象, 找到那些断线的 需要回收的对象 就清除掉。首先大家要理解 垃圾回收也是一个线程 在运行,它的本质和其他我们工作的线程没什么区别,既然是线程就会有占用 就会有阻塞。

2024-04-11 16:45:04 760

原创 JVM修炼之路【9】- jvm中的引用、可达性分析法

如果是一般的强引用,SoftReference对象是有引用的 既然有引用说明还在用它 不会被回收,但是它是软引用 所以它比较脆弱 内存不足的时候照样被jvm回收。但是有一个这个地址丢失了 栈根本不知道 对象在堆的什么地方,彻底失联, 那这个对象就成了断了线的风筝, 无人问津。, 这个强字很好理解 既然这对象被引用了 那么 除非线程运行结束 它肯定是不会被垃圾回收期回收的 因为它是可达的。作为起始点,从这些对象开始遍历,能够到达的对象都被认为是"存活"的,而无法到达的对象则被标记为"可回收"的。

2024-04-10 22:27:48 423

原创 JVM修炼之路【8】- 直接内存

这种方式需要在Java堆内存和操作系统之间进行频繁的数据拷贝,尤其是在大量数据的读写场景下,会导致性能和效率的下降。而使用直接内存则可以避免这种拷贝过程,数据可以直接在操作系统的本地内存和文件之间进行传输,提高了IO操作的效率和性能。, 我们仅仅在堆上面创建一个 buffer对象 ,而这个对象读写数据的时候 直接通过直接内存 与 系统的文件内存 进行交互,这样根本不占用堆内存空间。直接内存是一种特殊的内存分配方式,它允许Java程序直接通过操作系统的本地内存分配接口来分配内存,而不受Java堆的限制。

2024-04-10 18:38:34 442

原创 JVM修炼之路【3】- 学会使用2个重要的工具 jclasslib 和 神器 arthas

(这个工作中排查问题非常有用,有时候运维把你的代码发到线上 有时候版本会发错 或者其他原因 导致线上代码运行和你本地的不一致 这时候线上是打包好的java字节码文件 你不可能用idea去看线上代码什么样 这时候怎么办 就用arthas 反编译 去看)上一节中我们认识了 字节码文件 知道里面有什么东西,那么随之而来的问题就是,我们平时写代码 工作中怎么查看一个java类 对应的字节码文件。去官网下载jar包, 因为它是java编写的 如果你是本地用就放本地,如果你是线上用就让运维把它放到线上的服务器。

2024-04-10 09:00:55 248

原创 视频上传-实现断点续传

这里单独要说 分布式文件系统 的概念,就是我们平时后端做上传图片 视频, 那么前端上传过来的这些东西 后端最后存在哪 这是个问题,大家平时打lol 或者steam 下载游戏 如果你下到一半 把网关了, 你还可以重新继续从刚才的进度下载。单纯的视频上传好办 前端传一个大文件的流 后端按照 MultipartFile 接受 然后读数据。如果是微服务架构中要集中管理 且多方调用,那么你存服务器的机器上面 肯定是不方便的。然后我们再说断点续传, 这是一个常见的功能性的东西, 并不是某个编程语言的特性。

2024-04-08 12:11:44 664

原创 关于mybatis #{} 和 ${} 的问题

防止 SQL 注入之外的错误:使用 #{} 能够保证参数值的类型和格式正确,避免了因为参数值格式不正确而导致的 SQL 执行错误。例如,如果参数值是字符串类型,MyBatis 会自动在字符串两侧添加引号,确保 SQL 语句的语法正确。防止 SQL 注入:当使用 #{} 时,MyBatis 会将参数值按照预定义的规则进行转义和处理,将参数值安全地插入到 SQL 语句中,从而避免了 SQL 注入的风险。但是这个问题是 单纯的拼接就没办法 有效的检查合法性 你也不知道 它会拼什么东西,

2024-04-07 18:07:30 109

原创 MybatisPlus分页插件的使用和原理

分页是后端开发的一个基础问题 基本上所有新手都会遇到,从前比较原始的分页 可能需要我们自己写分页 比如拿到分页参数 页数和num,然后自己把它拼接到sql里面去。Page对象表示分页信息,通过调用selectPage()方法执行分页查询,然后通过getRecords()方法获取查询结果。刚才说了 MybatisPlus拦截器在执行sql的时候 会把带page对象的sql 拦截 加工成分页语句。然后MybatisPlus拦截器在执行sql的时候 会把带page对象的sql 拦截 加工成分页语句。

2024-04-07 18:01:44 326

原创 全局过滤器实现Jwt校验

但是问题是如果后台有3个机器 那么你用jwt不影响 因为第一台机器登录成功 给你token 你拿着token如果第二次访问 遇到其他机器还是可以通过。但是session就有问题了如果你第二次遇到其他机器 其他几次不认识这个session id 所以还需要其他的手段来补足 比如拷贝session。为什么要进化 因为在分布式微服务中 会有很多个系统和服务相互配合 我们一般会用一个独立的网关服务来控制所有的请求入口。(jwt是一段token 它是登录的时候根据用户id生成的 也就说id一样 token就一样)

2024-03-21 21:29:10 340

原创 springcloud-Nacos 更强大的注册中心组件

环境隔离是一个非常重要的特性,刚才的集群隔离是为了负载均衡 和异地容灾, 而环境隔离一般是我们的开发环境 测试环境 生产环境做隔离,如果大家用过Apollo 动态配置的话就很好理解这个概念。但是 因为异地的那20个是以防不测的 正常情况下你跨城市调会比较慢 我希望是请求过来就优先调 深圳的100个实例 如果这100个全挂了 就去调异地的。回到上面的例子 服务A 要调用 服务B, 但是在实际的生产环境中,服务B可能有成百上千的实例 而且还不在一个城市 比如深圳机房有100个。

2024-03-20 17:02:08 621

原创 springcloud-Eureka注册中心

Springcloud为微服务开发提供了一个比较泛用和全面的解决框架,springcloud继承了spring一直以来的风格——不重复造轮子,里面很多的组件都是将其他其他开源组件改造集成进来。在众多的组件当中 我们先从springcloud修炼——Eureka注册中心开始吧。

2024-03-20 03:02:05 1030

原创 理解java特性:内部类

StaticInnerClass是一个静态内部类,它可以直接访问外部类OuterClass的静态成员outerStaticField,但不能直接访问外部类的非静态成员outerField。当一个类只在一个方法内部使用,并且不需要在其他地方访问时,可以考虑使用局部内部类。局部内部类可以用于实现一些辅助类或者工具类,使得方法内部的逻辑更加清晰,避免了将这些辅助类暴露在外部。就是上面的例子 内部类作为外部类的一个成员,直观的看就是在类里面 再定义一个类。注意上面的注释 静态内部类 他是个静态类 所以在。

2024-03-18 20:35:42 873

原创 适配器设计模式

类C就扮演了适配器的角色,它将类A的接口转换成了接口B,使得类A可以与预期使用接口B的客户端代码协作。bird类是我们不能改的, 但是Adapter 类是自己的,我们先用Adapter 实现SkyDream接口 在Adapter 职中把bird引进来作为一个私有属性 ,然后调用flyToSky方法。假设原本情况是这样的:类A实现了接口B,但是由于某些特殊原因,A不想直接实现B接口中的方法。然后,引入了类C,它实现了接口B,并且在C中重写了B接口的方法,但实际上在C中的方法中调用了类A的实现。

2024-03-18 12:02:05 474

原创 理解java特性:抽象类和接口

答案是接口 因为飞是不是一个基础属性 而是一个选择性的行为 有的动物会飞 有的动物不会飞 那么会飞的动物就实现飞的接口就可以了。从前的接口aaa: 里面定义了 3个方法 1 2 3, 这时候有100个类实现了这个接口 也就必须每个类实现这3个方法。答案是抽象类 因为吃是动物的一个基础属性 是个动物都会吃 不存在 不吃东西的动物,所以它放入抽象类中。而且更神奇的是 默认方法也允许你重写,你重写就调用重写的方法,不重写就调用接口中的默认方法。这里有一个重要的理解: 抽象类是定义的抽象, 而接口是行为的抽象。

2024-03-17 17:59:00 336

原创 理解Java特性:多态

这样的好处在于 你可以解耦 继承关系中的方法调用 比如这个方法 show(Animal animal) 参数是 animal, 你可以传任何继承animal对象的多态引用 它就会自动去调用子类对象的方法 , 是不是很方便!那么当这个 a1 去调用 show方法的时候: 他就会去调用子类的方法 而不是自己的方法。必须是重写父类的方法才能多态 如果你在子类写一个父类里面没有的新方法 你去多态调用就会报错。java的特性里面绕不过去的一个概念 就是 多态,多态是继承的基础上一个更高级的特性。

2024-03-17 01:55:04 362

原创 值传递和引用传递,方法的内存原理

上面的代码中 main主方法先入栈 接着开始执行addMethod方法 于是这个方法入栈 这时候它的参数中有a 变量a就把他的值的副本传给方法 意味着 复制了一个10 给方法 这个10 和原来的a 就没有什么关系了。这就是引用传递, 在java的内存模型中 对象是创建在堆上面, 堆是一块内存区域,他的引用的值是堆上的内存地址 打个比方 比如0001。这是为什么 因为值传递 传递的是该值的副本, 在java的内存模型 中 方法的执行 是栈在控制,每个方法将要被执行的是 就准备入栈 执行完之后就会出栈。

2024-03-01 19:49:51 335

原创 JVM修炼之路【7】-JVM内存模型

java虚拟机管理这块内存,所以我们也叫运行时数据区域很多介绍jvm的资料中 上来就说内存模型 这会让新手比较懵逼,所以我的博客专栏里面:先说 java程序执行的整个过程, 再说编译后的字节码文件,字节码文件的加载也就是类加载过程, 最后加载到jvm之后 发生了什么jvm怎么处理 怎么存储 怎么运行这些加载进来的字节码文件, 这时候才引出了。

2024-01-15 11:30:55 976

原创 JVM修炼之路【6】- 理解双亲委派机制(且如何破坏此机制)

/ 1. 检查是否已经加载过Class<?= null) {// 2. 如果不是系统类加载器,则委派给父加载器if (!= null) {= null) {// 父加载器无法加载,继续尝试自己加载// 3. 尝试使用自定义的类加载器加载= null) {// 4. 如果以上步骤都无法加载,则抛出 ClassNotFoundException。

2024-01-07 11:56:15 407

原创 JVM修炼之路【5】-类加载器的分类

类加载器的任务就是把 java字节码文件内容 加载到 JVM 中去。

2024-01-04 23:43:39 459

原创 JVM修炼之路【4】- 类的生命周期/加载

理一下,java 编译后的字节码文件,我们已经熟悉了 字节码文件长什么样,字节码文件中有哪些内容,那么下一步就是使用类加载器 把字节码文件加载到JVM中。

2024-01-03 15:47:06 963

原创 JVM修炼之路【2】-正确的认识 字节码文件

上一篇中认识了JVM的基本组成,我们说JVM只认识字节码文件。那么在字节码文件进入JVM之前,我们先认识了解字节码文件长什么样,我们作为工程师不需要去死扣底层的理论知识,但是我们只是需要正确的打开字节码文件 知道里面有哪些部分组成,正确的认识和识别这些部分。

2023-12-30 13:46:27 543

原创 理解策略模式

策略模式的理解就是当代码里面的某个地方遇到了多种选择,多种方案,多种可能性的时候。最笨的方法就是针对不同的选择 做if-else,然后分别选择各种方案。所有的方案实现一个统一的接口(方案的总和)。在它的构造函数中 对 Buyer 进行赋值,这里利用了java中的多态特性,实现了同一个接口的不同实现。付款是一个方案的总和,付款下面有各种方案 比如 一折 三折 五折 八折。但是这样代码会非常的臃肿和不好维护,因为所有的方案都写到了一个方法里面。注意策略模式里面这些一个个方案都是独立 互斥的,你只能多选一。

2023-09-19 20:41:16 499

原创 Git 常用命令

这个命令是重置,这个命令非常有用,假如你手贱 本地提交了master分支, 但是又没有 直接推送远程master分支的权限,这时候就卡在本地提交 未推送 到远程的地方。要回滚提交也非常麻烦。其实提交记录在 可视化界面也可以看的很清晰。这个命令主要是能查到每次提交的 commit id。

2023-07-14 11:15:11 1015

原创 Java 泛型

泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为。什么叫参数限制呢 之前T是什么类型都可以 ,但是你不想T的类型完全无限制,这种情况 可以用java的继承思想 来用父类限定子类。这里返回值是泛型T 也就是 set进去的T是什么类型 你调用get方法的时候取出来的T就是什么类型。这里对比之前的get方法 这是把方法类型从T 换成了类< T > ,

2023-07-12 18:30:01 86

原创 Java异常体系

自定义异常其实很简单/*** 自定义异常的普遍标准就是 一般都是以Exception结尾,说明该类是一个异常类* 一个无参构造和 和一个带异常信息的有参构造} }自定义异常一般用于 业务场景 ,有些场景 从代码逻辑上看不报错,但是业务上报错,这种情况你就可以手动 throw new VcamlException() 把这个异常往上抛。

2023-07-07 11:39:50 84

原创 【JAVA8新特性】 stream流API

这个名字本身就容易让新手混淆,因为编程领域里面有很多东西名字都带有stream,比如BIO 里面有的IO流 inputstream ,outputstream, 比如大数据里面有流式计算,会有什么什么steam之类的。流 stream怎么理解这个东西?

2023-07-03 11:20:20 172

原创 【spring核心】Spring的事务传播机制

如果A中也有事务、B中也有事务,那么B会加入到A中去,变成一个事务,这时,要么都成功,要么都失败。被调用者B会以非事务方式运行(直接提交),如果当前有事务,也就是A中有事务,A会被挂起(不执行,等待B执行完,返回);如果A中有事务,则B方法的事务加入A事务中,成为一个事务(一起成功,一起失败),如果A中没有事务,那么B就以非事务方式运行(执行完直接提交);如果A中有事务,则B方法的事务加入A事务中,成为一个事务(一起成功,一起失败),如果A中没有事务,那么B就以非事务方式运行(执行完直接提交);

2023-06-07 04:17:12 92

原创 操作系统 内存OOM-Kill 机制

内存是计算机中用于存储程序、数据和操作系统本身所需信息的关键资源。操作系统的内存具有以下几个方面的功能:**内存管理:**操作系统负责管理计算机系统中的物理内存和虚拟内存。它跟踪哪些内存位置是空闲的,哪些是已被占用的。内存管理器分配和回收内存,以满足应用程序和操作系统的内存需求。虚拟内存:操作系统使用虚拟内存技术将物理内存与逻辑地址空间进行映射。它允许每个进程拥有独立的地址空间,并将进程所需的内存页面映射到物理内存或磁盘上的页面文件中。内存保护。

2023-06-06 21:06:18 259

原创 Redis修炼 集群篇 理解集群架构基础

如果目标节点不持有数据,它会向请求节点返回一个MOVED错误,指示请求节点重新发送请求到正确的节点。如果请求节点不持有该槽的数据,它会向其他节点发送一个请求,询问它们是否持有该槽的数据。客户端发送一个查询请求到Redis集群中的任意一个节点,该节点被称为请求节点(requesting node)。请求节点根据MOVED错误的信息重新发送请求到正确的节点。目标节点收到请求后检查本地是否持有该槽的数据。如果目标节点持有数据,则它将数据返回给请求节点。当请求节点接收到正确节点的响应后,它将数据返回给客户端。

2023-06-06 04:53:19 36

原创 Redis修炼 原理篇 底层数据结构

redis是c语言实现的,但是c语言里面的string有很多问题 比如非二进制安全 比如获取长度的性能比较低, 所以redis自己搞了一个专门的数据结构来实现string。在这个c语言的结构体中,char buf 装具体的数据 关键第三个flags 它标明了结构体的大小类型,看右边 有不同的位大小 这样可以适配不同的大小,达到空间的合理利用。然后为什么管它叫动态字符串 因为它具备动态扩容的能力,因为redis的字符串是可以修改的,所以当它的值大小图片 alloc 属性的时候,redis会申请新的内存空间。

2023-06-05 03:57:39 40

原创 【spring核心】Spring中的事务控制和事务失效

READ_UNCOMMITTED(读取未提交):最低的隔离级别,允许事务读取未提交的数据,可能会导致脏读(Dirty Read)。:用于指定事务是否为只读事务。REQUIRED(默认值):如果当前存在事务,就加入到当前事务中,如果不存在事务,则创建一个新的事务。SUPPORTS:如果当前存在事务,就加入到当前事务中,如果不存在事务,则以非事务方式执行。:用于控制事务之间的隔离程度,即一个事务的操作对其他事务的可见性和影响。REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则挂起当前事务。

2023-06-04 20:52:31 89

原创 【spring核心】Bean的循环依赖和解决方案

这个很好理解 我们在bean的生命周期中说了bean实例化的时候 要注入属性值 这些属性可能就包括一些其他的bean这个很常见 比如你的一个bean里面 @autowired 注入了一些其他的bean但是A里面注入了B ,B里面又注入了A,这时候容器就犯难了 加载A的时候B还没好 加载B的时候A还没好。

2023-06-04 19:43:55 121

原创 【spring核心】Bean的生命周期

BeanPostProcessor的before()方法回调:在Bean的初始化之前,Spring容器会调用注册的BeanPostProcessor的before()方法。Aware接口属性注入:如果Bean实现了Spring提供的Aware接口(如ApplicationContextAware、BeanFactoryAware等),Spring容器会在属性填充后,通过相应的回调方法将相关的资源或容器注入到Bean中。然后执行bean的工厂后处理器:比如更改bean的作用域,做一些bean定义的拓展。

2023-06-04 19:17:25 89 1

原创 【spring核心】BeanFactory 和 ApplicationContext

这个系列 【spring核心】 分享一些spring核心的知识点和实践,主要是IOC和AOP现在框架越来越先进了 特别是springboot出现之后,很多底层的东西框架都帮我们做了,导致我们只能感知到表面的一些东西,用起来是很爽,但是用完之后我们还是要尝试学习一下底层的东西,这样可以让我们更深入的理解和体会。

2023-06-04 14:21:05 33

原创 什么是分布式架构

在入门dubbo之前。我们先得对分布式架构有一个基本的了解。在这个背景下 才好慢慢理解dubbo RPC框架。

2023-06-01 03:29:20 40

原创 【JUC】CountDownLatch

因为我们在多线程中经常要遇到一类场景就是你要等所有线程全部工作之后 才能往下走。比如你要等所有线程都获取数据 获取完整之后 装到一个集合里面往下走。这是一个多线程里面非常好用,也非常重要的工具类。然后将latch 作为每一个线程的参数。当一个线程执行完任务后让他-1。count 对应你的任务数量。然后就可以继续往下执行了。新手一定要使用熟练。

2023-05-31 22:14:09 46

原创 synchronized锁的优化 轻量级锁 锁膨胀 自旋锁 偏向锁

当一个线程访问一个同步块时,如果该同步块未被锁定,虚拟机会将对象头部的标记位设置为“轻量级锁”状态,并将当前线程的Thread ID记录在对象头部的指针中。是指将轻量级锁转换为重量级锁的过程。膨胀为重量级锁的过程包括操作系统级的线程阻塞和唤醒,涉及到操作系统的上下文切换,这对性能会有一定的影响。当一个线程请求获取锁时,如果锁已经被其他线程占用,该线程不会立即阻塞挂起,而是在一个循环中不断地进行自旋(空转)等待,尝试获取锁。如果自旋等待的线程自旋一段时间后仍未获取到锁,那么轻量级锁就会膨胀为重量级锁。

2023-05-31 19:36:17 63

原创 【JUC】ReentrantLock

顾名思义是可重入锁。它是synchronized的进化版,提供了对锁更灵活的控制。(乍一看像redis里面的分布式锁对吧,写个lock方法 里面写setnx)给个简单的例子 体会一下和synchronized的不同。它和 synchronized 有什么异同呢?而不是用synchronized{}去包裹。这种在控制锁粒度方面会更灵活一点。它获取锁和释放锁是通过调用方法。

2023-05-31 19:21:41 31

原创 synchronized 锁的使用

你也可以 synchronized 修饰方法 比如搞一个add()方法 把i++封装。所以这时候 我们用 synchronized 加锁 让这个操作具备原子性。但是这个count是integer类型 他是一个对象 而不是一个基础类型。可以看到我们创建了一个静态对象实例,用它来当锁。因为 i++ 这个操作不是原子性操作。这里就会有问题 你虽然给count加锁。但是你会发现 每次得到的是一个随机数。还记得经典的单例模式是怎么写的吗?它可能会出现两个线程同时操作了。这种情况下就是线程安全的。

2023-05-31 02:57:52 32

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除