mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2026-05-11 04:04:35 +08:00
u
This commit is contained in:
@@ -25,13 +25,7 @@
|
||||
<meta name="generator" content="Hexo 4.2.0">
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="book-container">
|
||||
|
||||
<div class="book-sidebar">
|
||||
@@ -55,421 +49,214 @@
|
||||
<li><a href="/" class="current-tab">首页</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li><a href="../">上一级</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/00 学好 Netty,是你修炼 Java 内功的必经之路.md.html">00 学好 Netty,是你修炼 Java 内功的必经之路.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/01 初识 Netty:为什么 Netty 这么流行?.md.html">01 初识 Netty:为什么 Netty 这么流行?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/02 纵览全局:把握 Netty 整体架构脉络.md.html">02 纵览全局:把握 Netty 整体架构脉络.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/03 引导器作用:客户端和服务端启动都要做些什么?.md.html">03 引导器作用:客户端和服务端启动都要做些什么?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/04 事件调度层:为什么 EventLoop 是 Netty 的精髓?.md.html">04 事件调度层:为什么 EventLoop 是 Netty 的精髓?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/05 服务编排层:Pipeline 如何协调各类 Handler ?.md.html">05 服务编排层:Pipeline 如何协调各类 Handler ?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/06 粘包拆包问题:如何获取一个完整的网络包?.md.html">06 粘包拆包问题:如何获取一个完整的网络包?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/07 接头暗语:如何利用 Netty 实现自定义协议通信?.md.html">07 接头暗语:如何利用 Netty 实现自定义协议通信?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/08 开箱即用:Netty 支持哪些常用的解码器?.md.html">08 开箱即用:Netty 支持哪些常用的解码器?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/09 数据传输:writeAndFlush 处理流程剖析.md.html">09 数据传输:writeAndFlush 处理流程剖析.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/10 双刃剑:合理管理 Netty 堆外内存.md.html">10 双刃剑:合理管理 Netty 堆外内存.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/11 另起炉灶:Netty 数据传输载体 ByteBuf 详解.md.html">11 另起炉灶:Netty 数据传输载体 ByteBuf 详解.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/12 他山之石:高性能内存分配器 jemalloc 基本原理.md.html">12 他山之石:高性能内存分配器 jemalloc 基本原理.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/13 举一反三:Netty 高性能内存管理设计(上).md.html">13 举一反三:Netty 高性能内存管理设计(上).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/14 举一反三:Netty 高性能内存管理设计(下).md.html">14 举一反三:Netty 高性能内存管理设计(下).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/15 轻量级对象回收站:Recycler 对象池技术解析.md.html">15 轻量级对象回收站:Recycler 对象池技术解析.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
<a class="current-tab" href="/专栏/Netty 核心原理剖析与 RPC 实践-完/16 IO 加速:与众不同的 Netty 零拷贝技术.md.html">16 IO 加速:与众不同的 Netty 零拷贝技术.md.html</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/17 源码篇:从 Linux 出发深入剖析服务端启动流程.md.html">17 源码篇:从 Linux 出发深入剖析服务端启动流程.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/18 源码篇:解密 Netty Reactor 线程模型.md.html">18 源码篇:解密 Netty Reactor 线程模型.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/19 源码篇:一个网络请求在 Netty 中的旅程.md.html">19 源码篇:一个网络请求在 Netty 中的旅程.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/20 技巧篇:Netty 的 FastThreadLocal 究竟比 ThreadLocal 快在哪儿?.md.html">20 技巧篇:Netty 的 FastThreadLocal 究竟比 ThreadLocal 快在哪儿?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/21 技巧篇:延迟任务处理神器之时间轮 HashedWheelTimer.md.html">21 技巧篇:延迟任务处理神器之时间轮 HashedWheelTimer.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/22 技巧篇:高性能无锁队列 Mpsc Queue.md.html">22 技巧篇:高性能无锁队列 Mpsc Queue.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/23 架构设计:如何实现一个高性能分布式 RPC 框架.md.html">23 架构设计:如何实现一个高性能分布式 RPC 框架.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/24 服务发布与订阅:搭建生产者和消费者的基础框架.md.html">24 服务发布与订阅:搭建生产者和消费者的基础框架.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/25 远程通信:通信协议设计以及编解码的实现.md.html">25 远程通信:通信协议设计以及编解码的实现.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/26 服务治理:服务发现与负载均衡机制的实现.md.html">26 服务治理:服务发现与负载均衡机制的实现.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/27 动态代理:为用户屏蔽 RPC 调用的底层细节.md.html">27 动态代理:为用户屏蔽 RPC 调用的底层细节.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/28 实战总结:RPC 实战总结与进阶延伸.md.html">28 实战总结:RPC 实战总结与进阶延伸.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/29 编程思想:Netty 中应用了哪些设计模式?.md.html">29 编程思想:Netty 中应用了哪些设计模式?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/30 实践总结:Netty 在项目开发中的一些最佳实践.md.html">30 实践总结:Netty 在项目开发中的一些最佳实践.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/Netty 核心原理剖析与 RPC 实践-完/31 结束语 技术成长之路:如何打造自己的技术体系.md.html">31 结束语 技术成长之路:如何打造自己的技术体系.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||||
|
||||
<div class="sidebar-toggle-inner"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
function add_inner() {
|
||||
@@ -479,9 +266,6 @@
|
||||
inner.classList.add('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function remove_inner() {
|
||||
|
||||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||||
@@ -489,9 +273,6 @@
|
||||
inner.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sidebar_toggle() {
|
||||
|
||||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||||
@@ -521,9 +302,6 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function open_sidebar() {
|
||||
|
||||
let sidebar = document.querySelector('.book-sidebar')
|
||||
@@ -547,13 +325,7 @@ function hide_canvas() {
|
||||
overlay.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<div class="off-canvas-content">
|
||||
|
||||
<div class="columns">
|
||||
@@ -635,37 +407,13 @@ function hide_canvas() {
|
||||
<p>FileChannel#transferTo() 的使用也非常简单,我们直接看如下的代码示例,通过 transferTo() 将 from.data 传输到 to.data(),等于实现了文件拷贝的功能。</p>
|
||||
|
||||
<pre><code>public void testTransferTo() throws IOException {
|
||||
|
||||
|
||||
|
||||
RandomAccessFile fromFile = new RandomAccessFile("from.data", "rw");
|
||||
|
||||
|
||||
|
||||
FileChannel fromChannel = fromFile.getChannel();
|
||||
|
||||
|
||||
|
||||
RandomAccessFile toFile = new RandomAccessFile("to.data", "rw");
|
||||
|
||||
|
||||
|
||||
FileChannel toChannel = toFile.getChannel();
|
||||
|
||||
|
||||
|
||||
long position = 0;
|
||||
|
||||
|
||||
|
||||
long count = fromChannel.size();
|
||||
|
||||
|
||||
|
||||
fromChannel.transferTo(position, count, toChannel);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
@@ -713,13 +461,7 @@ function hide_canvas() {
|
||||
<p>CompositeByteBuf 是 Netty 中实现零拷贝机制非常重要的一个数据结构,CompositeByteBuf 可以理解为一个虚拟的 Buffer 对象,它是由多个 ByteBuf 组合而成,但是在 CompositeByteBuf 内部保存着每个 ByteBuf 的引用关系,从逻辑上构成一个整体。比较常见的像 HTTP 协议数据可以分为<strong>头部信息 header</strong>和<strong>消息体数据 body</strong>,分别存在两个不同的 ByteBuf 中,通常我们需要将两个 ByteBuf 合并成一个完整的协议数据进行发送,可以使用如下方式完成:</p>
|
||||
|
||||
<pre><code>ByteBuf httpBuf = Unpooled.buffer(header.readableBytes() + body.readableBytes());
|
||||
|
||||
|
||||
|
||||
httpBuf.writeBytes(header);
|
||||
|
||||
|
||||
|
||||
httpBuf.writeBytes(body);
|
||||
|
||||
</code></pre>
|
||||
@@ -727,9 +469,6 @@ httpBuf.writeBytes(body);
|
||||
<p>可以看出,如果想实现 header 和 body 这两个 ByteBuf 的合并,需要先初始化一个新的 httpBuf,然后再将 header 和 body 分别拷贝到新的 httpBuf。合并过程中涉及两次 CPU 拷贝,这非常浪费性能。如果使用 CompositeByteBuf 如何实现类似的需求呢?如下所示:</p>
|
||||
|
||||
<pre><code>CompositeByteBuf httpBuf = Unpooled.compositeBuffer();
|
||||
|
||||
|
||||
|
||||
httpBuf.addComponents(true, header, body);
|
||||
|
||||
</code></pre>
|
||||
@@ -741,37 +480,13 @@ httpBuf.addComponents(true, header, body);
|
||||
<p>从图上可以看出,CompositeByteBuf 内部维护了一个 Components 数组。在每个 Component 中存放着不同的 ByteBuf,各个 ByteBuf 独立维护自己的读写索引,而 CompositeByteBuf 自身也会单独维护一个读写索引。由此可见,Component 是实现 CompositeByteBuf 的关键所在,下面看下 Component 结构定义:</p>
|
||||
|
||||
<pre><code>private static final class Component {
|
||||
|
||||
|
||||
|
||||
final ByteBuf srcBuf; // 原始的 ByteBuf
|
||||
|
||||
|
||||
|
||||
final ByteBuf buf; // srcBuf 去除包装之后的 ByteBuf
|
||||
|
||||
|
||||
|
||||
int srcAdjustment; // CompositeByteBuf 的起始索引相对于 srcBuf 读索引的偏移
|
||||
|
||||
|
||||
|
||||
int adjustment; // CompositeByteBuf 的起始索引相对于 buf 的读索引的偏移
|
||||
|
||||
|
||||
|
||||
int offset; // Component 相对于 CompositeByteBuf 的起始索引位置
|
||||
|
||||
|
||||
|
||||
int endOffset; // Component 相对于 CompositeByteBuf 的结束索引位置
|
||||
|
||||
|
||||
|
||||
// 省略其他代码
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
@@ -805,9 +520,6 @@ httpBuf.addComponents(true, header, body);
|
||||
<p>ByteBuf 提供了两个 slice 切分方法:</p>
|
||||
|
||||
<pre><code>public ByteBuf slice();
|
||||
|
||||
|
||||
|
||||
public ByteBuf slice(int index, int length);
|
||||
|
||||
</code></pre>
|
||||
@@ -815,13 +527,7 @@ public ByteBuf slice(int index, int length);
|
||||
<p>假设我们已经有一份完整的 HTTP 数据,可以通过 slice 方法切分获得 header 和 body 两个 ByteBuf 对象,对应的内容分别为 "header" 和 "body",实现方式如下:</p>
|
||||
|
||||
<pre><code>ByteBuf httpBuf = ...
|
||||
|
||||
|
||||
|
||||
ByteBuf header = httpBuf.slice(0, 6);
|
||||
|
||||
|
||||
|
||||
ByteBuf body = httpBuf.slice(6, 4);
|
||||
|
||||
</code></pre>
|
||||
@@ -835,101 +541,29 @@ ByteBuf body = httpBuf.slice(6, 4);
|
||||
<p>在 Netty 源码的 example 包中,提供了 FileRegion 的使用示例,以下代码片段摘自 FileServerHandler.java。</p>
|
||||
|
||||
<pre><code>@Override
|
||||
|
||||
|
||||
|
||||
public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
|
||||
|
||||
|
||||
|
||||
RandomAccessFile raf = null;
|
||||
|
||||
|
||||
|
||||
long length = -1;
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
|
||||
|
||||
raf = new RandomAccessFile(msg, "r");
|
||||
|
||||
|
||||
|
||||
length = raf.length();
|
||||
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
|
||||
|
||||
ctx.writeAndFlush("ERR: " + e.getClass().getSimpleName() + ": " + e.getMessage() + '\n');
|
||||
|
||||
|
||||
|
||||
return;
|
||||
|
||||
|
||||
|
||||
} finally {
|
||||
|
||||
|
||||
|
||||
if (length < 0 && raf != null) {
|
||||
|
||||
|
||||
|
||||
raf.close();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
ctx.write("OK: " + raf.length() + '\n');
|
||||
|
||||
|
||||
|
||||
if (ctx.pipeline().get(SslHandler.class) == null) {
|
||||
|
||||
|
||||
|
||||
// SSL not enabled - can use zero-copy file transfer.
|
||||
|
||||
|
||||
|
||||
ctx.write(new DefaultFileRegion(raf.getChannel(), 0, length));
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
|
||||
// SSL enabled - cannot use zero-copy file transfer.
|
||||
|
||||
|
||||
|
||||
ctx.write(new ChunkedFile(raf));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
ctx.writeAndFlush("\n");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
@@ -937,121 +571,37 @@ public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception
|
||||
<p>从 FileRegion 的使用示例可以看出,Netty 使用 FileRegion 实现文件传输的零拷贝。FileRegion 的默认实现类是 DefaultFileRegion,通过 DefaultFileRegion 将文件内容写入到 NioSocketChannel。那么 FileRegion 是如何实现零拷贝的呢?我们通过源码看看 FileRegion 到底使用了什么黑科技。</p>
|
||||
|
||||
<pre><code>public class DefaultFileRegion extends AbstractReferenceCounted implements FileRegion {
|
||||
|
||||
|
||||
|
||||
private final File f; // 传输的文件
|
||||
|
||||
|
||||
|
||||
private final long position; // 文件的起始位置
|
||||
|
||||
|
||||
|
||||
private final long count; // 传输的字节数
|
||||
|
||||
|
||||
|
||||
private long transferred; // 已经写入的字节数
|
||||
|
||||
|
||||
|
||||
private FileChannel file; // 文件对应的 FileChannel
|
||||
|
||||
@Override
|
||||
|
||||
|
||||
|
||||
public long transferTo(WritableByteChannel target, long position) throws IOException {
|
||||
|
||||
|
||||
|
||||
long count = this.count - position;
|
||||
|
||||
|
||||
|
||||
if (count < 0 || position < 0) {
|
||||
|
||||
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
|
||||
|
||||
|
||||
"position out of range: " + position +
|
||||
|
||||
|
||||
|
||||
" (expected: 0 - " + (this.count - 1) + ')');
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (count == 0) {
|
||||
|
||||
|
||||
|
||||
return 0L;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (refCnt() == 0) {
|
||||
|
||||
|
||||
|
||||
throw new IllegalReferenceCountException(0);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
open();
|
||||
|
||||
|
||||
|
||||
long written = file.transferTo(this.position + position, count, target);
|
||||
|
||||
|
||||
|
||||
if (written > 0) {
|
||||
|
||||
|
||||
|
||||
transferred += written;
|
||||
|
||||
|
||||
|
||||
} else if (written == 0) {
|
||||
|
||||
|
||||
|
||||
validate(this, position);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return written;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 省略其他代码
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
@@ -1085,9 +635,6 @@ public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1095,9 +642,6 @@ public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||||
|
||||
</div>
|
||||
@@ -1113,17 +657,11 @@ public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception
|
||||
<script>
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
|
||||
|
||||
function gtag() {
|
||||
|
||||
dataLayer.push(arguments);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-NPSEEVD756');
|
||||
@@ -1149,9 +687,6 @@ public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception
|
||||
setCookie("lastPath", path)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setCookie(cname, cvalue) {
|
||||
|
||||
var d = new Date();
|
||||
@@ -1163,9 +698,6 @@ public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception
|
||||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCookie(cname) {
|
||||
|
||||
var name = cname + "=";
|
||||
@@ -1183,12 +715,6 @@ public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user