- 博客(71)
- 收藏
- 关注
原创 redis数据结构的整理
一:String类型数据结构底层是由SDS实现的。struct sdshdr{ //记录buf数组中已经使用字节的数量 //等于SDS所保存字符串的长度 int len; //记录buf数组中未使用字节的数量 int free; //字节数组,用于保存字符串 char buf[];};SDS遵循C字符串以空字符结尾的惯例,保存空字符的1字节空间不计算在SDS的len属性里面,并且为空字符分配额外的1字节空间,以及添加空字符到
2022-05-06 14:22:33
865
原创 类被卸载的条件
该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。加载该类的ClassLoader已经被回收。该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。如果有反射获取到了某个类的方法,那么这个类不能卸载。...
2022-01-10 20:52:54
688
原创 Netty为什么不是信号量驱动IO
信号驱动式IO对于TCP套接字产生的作用不大。因为该信号在TCP套接字中产生的过于频繁。以下条件均会导致对一个TCP套接字产生SIGIO信号:监听套接字上某个连接请求已经完成; 某个断连请求已经发起; 某个断连请求已经完成; 某个连接之半已经关闭; 数据到达套接字; 数据已经从套接字发送走; 发生某个异步错误。这么多条件都会触发SIGIO信号,导致应用进程对该信号一头雾水,没法确定套接字具体发生了什么事情。不过可以对TCP监听套接字可以使用SIGIO,因为对于监听套接字,产生SIGIO
2021-12-13 19:41:17
504
原创 Java序列化
序列化:将对象写入到IO流中 反序列化:从IO流中恢复对象 意义:序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。 使用场景:所有可在网络上传输的对象都必须是可序列化的,比如RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都是可序列化的,否则会出错;所有需要保存到磁盘的java对象都必须是可序列化的。通常建议:程序创建的每个Java
2021-12-10 17:43:54
350
原创 Jvm运维
1、远程debug-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044suspend:是不是等远程连接来了才开始启动进程 address:端口号2、jstack线程分析thread dump日志文件分析_旧路-优快云博客_dump日志分析jstack pid >a :获取栈信息输出到ajava -jar jcaxx.jar。在软件里打开a,就可以看到线程栈的情况3、飞行数据jvm运行时保留相关..
2021-12-10 17:11:54
719
原创 Java对象头
由于Java面向对象的思想,在JVM中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能,这些标记字段组成了对象头。1.对象头形式JVM中对象头的方式有以下两种(以32位JVM为例):1.1.普通对象|--------------------------------------------------------------|| Object Header (64 bits)
2021-12-10 10:39:09
2690
原创 For循环为什么不能对集合进行删除操作
增加for循环即foreach循环其实就是根据list对象创建一个iterator迭代对象,用这个迭代对象来遍历list,相当于list对象中元素的遍历托管给了iterator每次foreach循环时都有以下两个操作:iterator.hasNext(); //判读是否有下个元素 item = iterator.next();//下个元素是什么,并把它赋给item。1)在使用For-Each快速遍历时,ArrayList内部创建了一个内部迭代器iterator,使用的是hasNext和next(
2021-12-10 10:05:11
711
原创 Netty---ChannelOption
ChannelOption.SO_BACKLOG (一般用于option–>boss) BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程都处于工作是(用完了),用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。 ChannelOption.SO_REUSEADDR (一般用于option–>boss) SO_REUSEADDR 对应的是socket选项中SO_REUSEADDR,这个参数表示允许
2021-12-09 15:37:53
876
原创 Netty---Handler线程模型
每个handler都有一个executor,当事件流过的时候会判断是不是自己的executor,如果不是就提交一个任务进去。head和tail的executor是workerGroup里面的。用户自己的handler在添加的时候如果没有指定executor,那么使用的也是workerGroup。此时head、tail和用户自己的handler使用的就是同一个executor。如果此时用户的处理逻辑阻塞,那么等于这个IO线程阻塞,会影响到所有注册到此executor的通道。解决方法就是将耗时任务添加到异步
2021-12-09 15:19:32
505
原创 Netty---通道生成
在bind过程,反射构建了NioServerSocketChannel,然后进入init...... channel = channelFactory.newChannel(); init(channel);......init方法主要是设置通道属性,然后添加handlerIniter。 @Override void init(Channel channel) throws Exception { ... ... ... p.
2021-12-09 14:54:48
649
原创 Netty--writeAndFlush使用的buf回收
一般我们在handle里面申请一个buf,然后发送出去,这个buf在哪释放呢? @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buffer = ByteBufAllocator.DEFAULT.directBuffer(4); ctx.writeAndFlush(buffer); }A
2021-12-09 14:32:48
498
原创 Netty--read接收数据创建的buf回收
创建地点:NioByteUnsafe#read public final void read() { final ChannelConfig config = config(); final ChannelPipeline pipeline = pipeline(); final ByteBufAllocator allocator = config.getAllocator(); final RecvB
2021-12-09 11:29:12
186
原创 Netty---解码器/编码器
示例代码 // 必须先添加解码器/编码器 保证数据流动的顺序正确 ch.pipeline().addLast("decoder", new ProtobufDecoder(BalanceNetProtocol.BasePackage.getDefaultInstance()));
2021-12-08 18:02:34
991
原创 Netty -- read过程
NioEventLoop开启seletor循环后,当有key就绪时,会进入processSelectedKeys,最终进入NioEventLoop#processSelectedKey private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe(); if (!k.is.
2021-12-08 18:00:54
253
原创 Netty--selector开启
在注册的时候,最终进入unsafe的register方法,向eventLoop提交了一个任务。eventLoop第一次接受任务的时候就会开启一个线程。 @Override public void execute(Runnable task) { if (task == null) { throw new NullPointerException("task"); } boolean inEventLoop = in
2021-12-08 16:56:45
280
原创 Netty--write过程
示例代码public class SessionHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { BalanceNetProtocol.BasePackage basePackage = (BalanceNetProtocol.BaseP
2021-12-08 11:30:02
686
原创 Netty---组件说明
channel构建的时候会构建一个pipeline,pipeline含有channel的引用。handler添加的时候会构建一个context,包含着pipeline,所以context-->pipeline-->channel。channel在注册的时候会绑定一个eventLoop。eventLoop绑定一个selector和一个线程。channel就是一个通道,底层就是socket。EventLoopGroup就是eventLoop的集合。...
2021-12-07 11:25:40
93
原创 Netty--bind过程
示例代码 serverBootstrap.group(bossGroup, workGroup) // 设置channel工厂 .channel(NioServerSocketChannel.class) .handler(new ChannelInitializer<ServerSocketChannel>() { @Override
2021-12-07 10:57:55
197
原创 Netty内存表示---handle与bitMapIds
handle是一个64位的long型。前32位表示属于chunk下的哪个节点。后32位如果不为0,代表是小于一页的内存。那么后32位就是bitMapIds,表示属于哪一页的哪一块位置。bitMapIds前26位代表属于bitMap数组的下标,后6位代表属于long中哪一位。...
2021-11-30 17:04:15
157
原创 Netty内存分配一
层级结构首先介绍些netty内存池的层级结构,主要分为Arena、ChunkList、Chunk、Page、Subpage这5个层级,这几个层级的关系由大到小,如下图所示:Arena代表1个内存区域,为了优化内存区域的并发访问,netty中内存池是由多个Arena组成的数组,分配时会每个线程按照轮询策略选择1个Arena进行内存分配。1个Arena由两个PoolSubpage数组和多个ChunkList组成。两个PoolSubpage数组分别为tinySubpa...
2021-11-29 17:50:23
575
原创 邮戳锁StampLock
基本理论所有获取锁的方法,都返回一个邮戳(Stamp),Stamp为0表示获取失败,其余都表示成功; 所有释放锁的方法,都需要一个邮戳(Stamp),这个Stamp必须是和成功获取锁时得到的Stamp一致; StampedLock是不可重入的;(如果一个线程已经持有了写锁,再去获取写锁的话就会造成死锁) StampedLock有三种访问模式: Reading(读模式):功能和ReentrantReadWriteLock的读锁类似 Writing(写模式):功能和ReentrantReadWr
2021-11-25 14:40:56
1385
原创 读写锁ReentrantReadWriteLock
AQS实现的工具类,需要明白的就是AQS的state代表的是什么。ReentrantLockReadWriteLock中的state同时表示写锁和读锁的个数。为了实现这种功能,state的高16位表示读锁的个数,低16位表示写锁的个数。AQS有两种模式:共享模式和独占模式,读写锁的实现中,读锁使用共享模式;写锁使用独占模式;另外一点需要记住的即使,当有读锁时,写锁就不能获得;而当有写锁时,除了获得写锁的这个线程可以获得读锁外,其他线程不能获得读锁。读锁,就是加锁的时候看头节点是不是读模式(共享模式)..
2021-11-24 16:58:12
141
原创 Netty---1---NioEventLoopGroup
使用:bossGroup = new NioEventLoopGroup();构造函数NioEventLoopGroup--->MultithreadEventLoopGroup。 protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory choo..
2021-11-19 18:51:31
357
原创 Netty零拷贝
1:Netty的接收和发送ByteBuffer使用直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用JVM的堆内存进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于使用直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。2:Netty的文件传输调用FileRegion包装的transferTo方法,可以直接将文件缓冲区的数据发送到目标Channel,避免通过循环write方式导致的内存拷贝问题。3:Netty提供Composi
2021-11-19 17:06:06
165
原创 零拷贝机制
文章转自框架篇:Linux零拷贝机制和FileChannel - 潜行前行 - 博客园零拷贝的好处减少或避免不必要的CPU数据拷贝,从而释放CPU去执行其他任务 零拷贝机制能减少用户空间和操作系统内核空间的上下文切换 减少内存的占用内核空间和用户空间内核空间:Linux自身使用的空间;主要提供进程调度、内存分配、连接硬件资源等功能 用户空间:提供给各个程序进程的空间;用户空间不具有访问内核空间资源的权限,如果应用程序需要使用到内核空间的资源,则需要通过系统调用来完成:从用户空间切换
2021-11-19 15:25:52
139
原创 堆外内存释放
结论:堆外内存只有在fullgc的时候才能够回收掉。先看普通对象回收,这里设置jvm参数,便于触发和观察gc-verbose:gc -XX:+PrintGCDetails -server -Xms20m -Xmx20m实例代码a结果
2021-11-12 17:32:06
869
原创 虚引用解析
结论:堆外内存只有在fullgc的时候才能够回收掉。先看普通对象回收,这里设置jvm参数,便于触发和观察gc-verbose:gc -XX:+PrintGCDetails -server -Xms20m -Xmx20m实例代码public class Test3 { public static final ReferenceQueue<Bu> QUEUE = new ReferenceQueue<>(); public static final L
2021-11-12 16:12:06
1337
原创 Future的get方法靠什么机制来阻塞
future底层其实也是AQS实现的阻塞,利用一个可见的state+cas+队列实现的看一下future子类FutureTask的实现private int awaitDone(boolean timed, long nanos) throws InterruptedException { final long deadline = timed ? System.nanoTime() + nanos : 0L; WaitNode q = null;.
2021-11-07 10:57:02
1265
原创 线程池解析
1、线程池构造 public ThreadPoolExecutor(int corePoolSize, // 核心线程数 int maximumPoolSize,// 最大线程数 // 超过一段时间没运行的线程会被回收, // 如果配置了核心线程可以被回收,核心线程也可以被回收
2021-11-07 00:03:47
135
原创 线程中断解析
线程中断相关方法介绍及区别1、interruptinterrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常,并且会清理掉线程的中断状态,抛出异常说明当前线程阻塞的代码已经被中断,不需要继续保持中断状态了。2、i.
2021-11-06 18:22:20
163
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人