java
文章平均质量分 66
记录大学生成为Java工程师学习路上的一点一滴
玉面大蛟龙
阿里巴巴后端工程师
展开
-
Effective Java 读书笔记
接口只应该用来定义类型,而不是用来导出常量标明实现了具有某种属性的接口 六、Lambda和表达式。原创 2024-05-02 23:46:17 · 684 阅读 · 3 评论 -
Java LinkedList解密
LinkedList其实底层是链表:当初始化的时候,会将链表这个节点的值、prev指针和next指针初始化。原创 2024-01-03 22:01:28 · 1075 阅读 · 1 评论 -
Java ArrayList解密
堆栈过程图示:└── if (size == elementData.length) // 判断是否需要扩容├── grow(minCapacity) // 扩容│ └── newCapacity = oldCapacity + (oldCapacity >> 1) // 计算新的数组容量│ └── Arrays.copyOf(elementData, newCapacity) // 创建新的数组// 添加新元素// 添加成功。原创 2024-01-01 19:06:14 · 941 阅读 · 0 评论 -
JVM学习(十四):垃圾收集器(万字介绍CMS、G1)
在JDK 1.5时期,Hotspot推出了一款在强交互应用中几乎可认为有划时代意义的垃圾收集器:CMS (Concurrent-Mark-Sweep)收集器,这款收集器是HotSpot虚拟机中第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。CMS收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间。停顿时间越短(低延迟)就越适合与用户交互的程序,良好的响应速度能提升用户体验。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度。原创 2023-06-02 22:13:15 · 6083 阅读 · 0 评论 -
JVM学习(十三):面试中绕不开的String
String实现了Serializable接口,表示字符串是支持序列化的;实现了Comparable接口,表示String可以比较大小。原创 2023-05-30 21:43:34 · 702 阅读 · 0 评论 -
JVM学习(十二):执行引擎
大部分的程序代码转换成物理机的目标代码或虚拟机能执行的指令集之前,都需要经过上图中的各个步骤。其中,黄色是javac前端编译器编译的过程,绿色是解释执行的过程,蓝色是编译执行的过程。1、什么是解释器(Interpreter),什么是JIT编译器?解释器:当Java虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。JIT (Just In Time Compiler)编译器。原创 2023-05-29 18:46:53 · 676 阅读 · 0 评论 -
JVM学习(十一):对象的实例化内存布局与访问定位
意思是所有用过的内存在一边,空闲的内存在另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那边挪动一段与对象大小相等的距离罢了。将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。意思是虚拟机维护了一个列表,记录上哪些内存块是可用的,再分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容。实现:通过栈上的reference指向堆中的句柄池中的指针,再由指针指向对象实例和方法区中的类元数据。原创 2023-05-17 20:22:10 · 663 阅读 · 0 评论 -
JVM学习(十):方法区
对栈不熟悉的同学可以参考我的文章:JVM学习(八):虚拟机栈(字节码程度深入剖析)_玉面大蛟龙的博客-CSDN博客 对堆不熟悉的同学可以参考我的文章:JVM学习(九):堆_玉面大蛟龙的博客-CSDN博客 方法区、堆和栈的关系如图: 《Java虚拟机规范》中明确说明:"尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于HotSpotJVM而言,方法区还有一个别名叫做Non-H原创 2023-05-09 20:13:16 · 589 阅读 · 0 评论 -
JVM学习(九):堆(万字剖析)
Java虚拟机规范》中对Java堆的描述是:所有的对象实例以及数组都应当在运行时分配在堆上(The heap is the run-time data area from which memory for all class instances and arrays is allocated )。《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除(因为垃圾收集的时候才会去扫描垃圾)。原创 2023-05-01 18:13:18 · 1315 阅读 · 0 评论 -
JVM学习(八):虚拟机栈(字节码程度深入剖析)
由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。 基于栈设计的优点是跨平台,指令集小,编译器容易实现;缺点是性能下降,实现同样的功能需要更多的指令。 有不少Java开发人员一提到Java内存结构,就会非常粗粒度地将JVM中的内存区理解为仅存Java堆(heap) 和 Java栈(stack),这是不正确的。 栈是运行时的单位,而堆是存储的单位。 即:栈解决程序的运行问题,即程序如何执行,或者说原创 2023-04-25 21:13:02 · 1070 阅读 · 0 评论 -
面试常问:Java中实例变量和局部变量的区别
— 类变量: static修饰。在linking的prepare阶段:给类变量默认赋值;然后在initial阶段:给类变量显式赋值,即静态代码块赋值。—— 实例变量:随着对象的创建,会在堆空间中分配实例变量空间,并进行默认赋值。生命周期与类对象相同。:包括方法形参、方法局部变量、代码块内局部变量。:在使用前,都经历过默认初始化赋值。必须要进行显式赋值!原创 2023-04-21 21:10:57 · 215 阅读 · 0 评论 -
JVM学习(七):运行时数据区(精讲)
JVM中的程序计数寄存器(Program counter Register)中, Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。这里并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更加贴切(也称为程序钩子),并且也不容易引起一些不必要的误会。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。原创 2023-05-09 20:29:53 · 811 阅读 · 0 评论 -
JVM学习(六):类加载子系统
类加载器子系统负责从文件系统或者网络中加载class文件,class文件在文件开头有特定的文件标识。ClassLoader只负责class文件的加载,至于它是否可以运行,则由ExecutionEngine决定。加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)原创 2023-04-18 21:15:11 · 693 阅读 · 0 评论 -
JVM学习(五):JVM运行时参数
注意:只有显式使用Eden区和Survivor区的比例,才会让比例生效,否则比例都会自动设置,至于其中的原因,请看下面的-XX:+UseAdaptiveSizePolicy中的解释,最后推荐使用默认打开的-XX:+UseAdaptiveSizePolicy设置,并且不显示设置-XX:SurvivorRatio。默认开启,将会导致Eden区和Survivor区的比例自动分配,因此也会引起我们默认值 -XX:SurvivorRatio=8失效,所以真实比例可能不是8,比如可能是6等。原创 2023-01-27 17:16:21 · 1344 阅读 · 0 评论 -
JVM学习(四):Arthas的安装与使用
Arthas(阿尔萨斯)是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab自动补全功能,进一步方便进行问题的定位和诊断。原创 2023-01-27 14:32:25 · 719 阅读 · 0 评论 -
JVM学习(三):聊聊内存泄漏(memory leak)
可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一个对象是否还被引用。那么对于这种情况下,由于代码的实现不同就会出现很多种内存泄漏问题(让JVM误以为此对象还在引用中,无法回收,造成内存泄漏)。用一句话来概括:对象还在被使用,但不需要。原创 2023-01-17 15:34:28 · 1010 阅读 · 0 评论 -
JVM学习(二):JVM监控及诊断工具-命令行篇
性能诊断是软件工程师在日常工作中需要经常面对和解决的问题,在用户体验至上的今天,解决好应用的性能问题能带来非常大的收益。Java 作为最流行的编程语言之一,其应用性能诊断一直受到业界广泛关注。可能造成Java应用出现性能问题的因素非常多,例如线程控制、磁盘读写、数据库访问、网络I/o、垃圾收集等。想要定位这些问题,一款优秀的性能诊断工具必不可少。接下来就给大家介绍Oracle自带的命令行诊断工具。原创 2023-01-14 18:42:33 · 1177 阅读 · 0 评论 -
JVM学习(一):简单聊聊性能调优这门艺术
运行日志异常堆栈GC日志线程快照堆转储快照。原创 2023-01-04 15:55:34 · 433 阅读 · 0 评论 -
Spring原理学习(六):Spring实现动态代理时对jdk和cglib的选择
spring当中不需要我们直接去用jdk或者cglib,它提供了ProxyFactory来方便地创建代理,那么他如何选择代理方法呢?我打算通过AOP中的切面来讲解这一部分。原创 2023-04-14 15:53:19 · 990 阅读 · 0 评论 -
Spring原理学习(五):一篇讲清楚动态代理(jdk和cglib)的使用、原理和源码
在下面的模拟中,我们的代理目标是Target类,他实现了Foo接口。在main方法中,我们模拟jdk实现动态代理的方法,来模拟实现AOP代理增强。需要注意的一点是:jdk只能针对接口代理。运行结果:需要注意:代理对象Proxy 和 代理目标Target是兄弟关系,他们都实现了Foo接口。所以,目标类Target也可以是final类型,这点与cglib实现的动态代理不同。原创 2023-04-13 21:29:49 · 2345 阅读 · 0 评论 -
Spring原理学习(四):Scope的介绍及其失效解决方案
虽然上述四种方法各不相同,但理念基本相同,都是延迟其他scope bean的获取。他们都是不直接获取多例,而是在中间加一个对象,通过这个对象等到运行时再去获取多例bean更推荐使用BeanFactory 或 ApplicationContext,因为更加简洁,且不像代理一样会造成一定的性能损耗。原创 2023-04-08 17:06:39 · 1495 阅读 · 0 评论 -
Spring原理学习(三):BeanFactory后处理器原理解析与模拟实现
我们已经简单介绍了 BeanFactory后处理器 的作用,今天我们先再来再次体验一下。先准备一个主启动类:然后准备一个bean,上面加了@Configuration和 @Bean 注解;并且加上了@ComponentScan 注解,应该能扫描到加有@Component注解的Bean2。所以config容器里应该有5个bean:config本身、扫描到的bean2、自己管理的三个(bean2、sqlSessionFactory、druidDataSource)。原创 2023-04-07 00:13:00 · 433 阅读 · 0 评论 -
Spring原理学习(二):Bean的生命周期和Bean后处理器
倘若是为了面试,请背下来下面这段:spring的bean的生命周期主要是创建bean的过程,一个bean的生命周期主要是4个步骤:实例化、属性注入、初始化、销毁。原创 2023-04-04 22:44:57 · 861 阅读 · 0 评论 -
Netty学习(七):心跳检测机制
所谓心跳, 即在TCP长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保TCP连接的有效性.心跳机制主要是客户端和服务端长时间连接时,客户端需要定时发送心跳包来保证自己是存活的,否则一个连接长时间没有作用就会浪费服务端的资源。原创 2023-03-13 15:09:16 · 4274 阅读 · 0 评论 -
Netty学习(六):netty核心模块组件
Channel也提供异步的网络VO操作(如建立连接,读写,绑定端口),异步调用意味着任何IO调用都将立即返回,并且不保证在调用结束时所请求的IO操作已完成,调用立即返回一个ChannelFuture实例,通过注册监听器到ChannelFuture 上,可以VO操作成功、失败或取消时回调通知调用方。入站事件和出站事件在一个双向链表中,入站事件会从链表head往后传递到最后一个入站的 handler,出站事件会从链表tail往前传递到最前一个出站的handler,两种类型的 handler互不干扰。原创 2023-03-12 15:17:42 · 359 阅读 · 0 评论 -
Netty学习(五):异步模型
异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的组件在完成后,通过状态、通知和回调来通知调用者。Netty中的IO操作是异步的,包括 Bind、Write、Connect 等操作会简单的返回一个ChannelFuture。调用者并不能立刻获得结果,而是通过Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果Netty 的异步模型是建立在 future 和 calback 的之上的。callback 就是回调。原创 2023-03-08 00:40:43 · 285 阅读 · 0 评论 -
Netty学习(四):TaskQueue中Task的三种典型使用场景
在前文Netty学习(三):Netty线程模型和代码示例中我们学习了netty的线程模型。其中,NIOEventLoop中有两个很重要的部分,一个是Selector,一个是TaskQueue。今天我们要来介绍TaskQueue。我们知道,Pipeline中的一些重量级任务,会放入TaskQueue中异步处理,那么TaskQueue是如何处理这些Task的呢?@Override//比如这里我们有一个非常耗时长的业务-> 异步执行 -> 提交该channel 对应的。原创 2023-03-06 21:07:26 · 199 阅读 · 0 评论 -
Netty学习(三):Netty线程模型和代码示例
Netty学习(二):线程模型。原创 2023-03-02 15:16:06 · 1028 阅读 · 0 评论 -
Netty学习(二):线程模型
不同的线程模式,对程序的性能有很大影响,为了搞清Netty线程模式,我们来系统的讲解下各个线程模式,最后看看Netty 线程模型有什么优越性.目前存在的线程模型有:传统阻塞IO服务模型Reactor模式。原创 2023-03-01 17:28:56 · 596 阅读 · 0 评论 -
Netty学习(一):Netty概述
Netty 对JDK自带的NIO 的API进行了封装,解决了上述问题。原创 2023-03-01 10:47:50 · 416 阅读 · 0 评论 -
NIO与零拷贝
零拷贝是网络编程的关键,很多性能优化都离不开。在Java程序中,常用的零拷贝有mmap(内存映射)和 sendFile。那么,他们在OS里,到底是怎么样的一个的设计?我们分析mmap和 sendFile这两个零拷贝另外我们看下NIO中如何使用零拷贝。原创 2023-02-27 17:24:34 · 607 阅读 · 0 评论 -
RabbitMQ学习(十一):RabbitMQ 集群
而此时又有个在深圳的业务(Client 深圳)需要向 exchangeA 发送消息,那么(Client 深圳) (broker 北京)之间有很大的网络延迟,(Client 深圳) 将发送消息至 exchangeA 会经历一定的延迟,尤其是在开启了 publisherconfirm 机制或者事务机制的情况下,(Client 深圳) 会等待很长的延迟时间来接收(broker 北京)的确认信息,进而必然造成这条发送线程的性能降低,甚至造成一定程度上的阻塞。确保负载均衡服务的可靠性同样显得十分重要。原创 2023-02-26 14:59:26 · 554 阅读 · 0 评论 -
RabbitMQ学习(十):幂等性、优先级队列、惰性队列
消费者在消费 MQ 中的消息时,MQ 已把消息发送给消费者,消费者在给 MQ 返回 ack 时网络中断,故 MQ 未收到确认信息,该条消息会重新发给其他的消费者,或者在网络重连后再次发送给该消费者,但实际上该消费者已成功消费了该条消息,这就造成了消息的重复消费。当 RabbitMQ 需要释放内存的时候,会将内存中的消息换页至磁盘中,这个操作会耗费较长的时间,也会阻塞队列的操作,进而无法接收新的消息。默认情况下,当生产者将消息发送到 RabbitMQ 的时候,队列中的消息会尽可能的存储在内存之中,原创 2023-02-23 15:58:01 · 588 阅读 · 0 评论 -
RabbitMQ学习(十):发布确认高级
在生产环境中由于一些不明原因,导致 RabbitMQ 重启,在 RabbitMQ 重启期间生产者消息投递失败导致消息丢失,需要手动处理和恢复。在这样比较极端的情况,当RabbitMQ 集群不可用的时候,无法投递的消息该如何处理呢?如何才能进行 RabbitMQ 的消息可靠投递呢?原创 2023-02-22 16:28:01 · 465 阅读 · 0 评论 -
RabbitMQ学习(九):延迟队列
发起一个请求http://localhost:8080/ttl/sendMsg/嘻嘻嘻第一条消息在 10S 后变成了死信消息,然后被消费者消费掉,第二条消息在 40S 之后变成了死信消息,然后被消费掉,这样一个延时队列就打造完成了。不过,如果这样使用的话,岂不是每增加一个新的时间需求,就要新增一个队列,这里只有 10S 和 40S两个时间选项,如果需要一个小时后处理,那么就需要增加 TTL 为一个小时的队列,如果是预定会议室然后提前通知这样的场景,岂不是要增加无数个队列才能满足需求?原创 2023-02-20 15:48:00 · 904 阅读 · 0 评论 -
RabbitMQ学习(八):死信队列
死信,顾名思义就是无法被消费的消息,一般来说,producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信。有死信自然也有死信队列。应用场景:1、为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ 的死信队列机制,当消息消费发生异常时,将消息投入死信队列中。2、用户在商城下单成功并点击去支付后在指定时。原创 2023-02-17 14:23:45 · 403 阅读 · 0 评论 -
RabbitMQ学习(七):交换器
在之前的内容中,我们创建了一个工作队列。我们假设的是工作队列背后,每个任务都恰好交付给一个消 费者(工作进程)。在今天的内容中,我们将做一些完全不同的事情——我们将消息传达给多个消费者。这种模式 称为 “发布/订阅为了说明这种模式,我们将以一个简单的日志系统为例。它将由两个程序组成:第一个程序将发出日志消 息,第二个程序是消费者。其中我们会启动两个消费者,其中一个消费者接收到消息后把日志存储在磁盘, 另外一个消费者接收到消息后把消息打印在屏幕上,事实上第一个程序发出的日志消息将广播给所有消费 者。原创 2023-02-16 15:07:09 · 457 阅读 · 0 评论 -
RabbitMQ学习(六):发布确认
confirm 模式最大的好处在于他是异步的,一旦发布一条消息,生产者应用程序就可以在等信道返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者应用便可以通过回调方法来处理该确认消息,如果 RabbitMQ 因为自身内部错误导致消息丢失,就会发送一条 nack 消息,生产者应用程序同样可以在回调方法中处理该 nack 消息。当然这种方案仍然是同步的,也一样阻塞消息的发布。因为如果没有确认发布的消息就会阻塞所有后续消息的发布,这种方式最多提供每秒不超过数百条发布消息的吞吐量。原创 2023-02-15 16:08:47 · 271 阅读 · 0 评论 -
RabbitMQ学习(五):RabbitMQ持久化
在最开始的时候我们学习到 RabbitMQ 分发消息采用的轮训分发,但是在某种场景下这种策略并不是很好,比方说有两个消费者在处理任务,其中有个消费者 1 处理任务的速度非常快,而另外一个消费者 2处理速度却很慢,这个时候我们还是采用轮训分发的话就会到这处理速度快的这个消费者很大一部分时间处于空闲状态,而处理慢的那个消费者一直在干活,这种分配方式在这种情况下就不合理,但是。但是需要注意的就是如果之前声明的队列不是持久化的,需要把原先队列先删除,或者重新创建一个持久化的队列,不然就会出现错误。原创 2023-02-14 16:22:19 · 2389 阅读 · 0 评论 -
RabbitMQ学习(四):消息应答
如果消费者由于某些原因失去连接(其通道已关闭,连接已关闭或 TCP 连接丢失),导致消息未发送 ACK 确认,RabbitMQ 将了解到消息未完全处理,并将对其重新排队。,因为这种模式如果消息在接收到之前,消费者那边出现连接或者 channel 关闭,那么消息就丢失了,当然另一方面这种模式消费者那边可以传递过载的消息,,当然这样有可能使得消费者这边由于接收太多还来不及处理的消息,导致这些消息的积压,最终使得内存耗尽,最终这些消费者线程被操作系统杀死。,我们将丢失正在处理的消息。原创 2023-02-13 15:52:50 · 312 阅读 · 0 评论