<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[停止更新]]></title><description><![CDATA[停止更新]]></description><link>https://blog.csdn.net/tracker_w</link><language>zh-cn</language><generator>https://blog.csdn.net/</generator><copyright><![CDATA[Copyright &copy; tracker_w]]></copyright><item><title><![CDATA[Maven中如何跳过不支持skip参数的插件执行]]></title><link>https://blog.csdn.net/tracker_w/article/details/123383411</link><guid>https://blog.csdn.net/tracker_w/article/details/123383411</guid><author>tracker_w</author><pubDate>Wed, 09 Mar 2022 17:52:33 +0800</pubDate><description><![CDATA[我们知道，很多maven官方插件都支持skip参数，命令行指定skip=true即可跳过此插件的执行，非常方便。但是很多第三方的插件根本就不支持skip参数，无法通过命令行传参的方式跳过插件的执行。
我们可以用一些非官方的方式绕过这个限制。总体思路为，将你想要跳过的插件的phase参数指定为一个不存在的phase，这样maven在执行的时候就会忽略这个插件。例如：
	
&lt;properties&gt;
    &lt;mvn.jarvis.skip&gt;package&lt;/mvn.jarvis.s]]></description><category></category></item><item><title><![CDATA[快速彻底理解字符集和字符集编码的区别]]></title><link>https://blog.csdn.net/tracker_w/article/details/121195046</link><guid>https://blog.csdn.net/tracker_w/article/details/121195046</guid><author>tracker_w</author><pubDate>Sun, 07 Nov 2021 18:35:10 +0800</pubDate><description><![CDATA[很多文章搞长篇大论大讲特讲人类为了让计算机能够准确表示各种字符的演化历史，这完全是没有必要的，几句话就能说明白。
"字符集"和"字符集编码"是两回事
字符集(Charset Set)，仅仅是一套从【字符】到【数字】的映射字典，它只规定了应该用什么数字来标识字符，仅此而已，至于计算机在存储的时候应该用什么字节来标识，字符集是根本不管这事的。Unicode, GB2312, ASCII都属于字符集。
字符集编码(Character Encoding)，专门规定了字符集中的字符在计算机中应该如何存储，说白了就是怎]]></description><category></category></item><item><title><![CDATA[如何手动编译Apple Silicon M1版本的JavaFX SceneBuilder]]></title><link>https://blog.csdn.net/tracker_w/article/details/118438793</link><guid>https://blog.csdn.net/tracker_w/article/details/118438793</guid><author>tracker_w</author><pubDate>Sat, 03 Jul 2021 13:15:14 +0800</pubDate><description><![CDATA[用JavaFX写GUI的朋友肯定少不了SceneBuilder这个神器，拖拖拽拽就能完成窗口布局。但是对于Mac M1的用户来说, SceneBuilder 并没有提供M1版本，官方的intel版本能用但是很卡，用起来很难受。下面我们来看看如何直接从源码构造M1版本的SceneBuilder。
准备工作
首先我们要下载M1版本的Zulu OpenJDK 16, 用来编译源码，然后要去Gluon的官网下载M1版本的JavaFX SDK， 如下：
JavaFX Mac OS X AArch64 SDK:
htt]]></description><category></category></item><item><title><![CDATA[[Golang实现JVM第七篇]实现invokevirtual和虚方法表]]></title><link>https://blog.csdn.net/tracker_w/article/details/108985446</link><guid>https://blog.csdn.net/tracker_w/article/details/108985446</guid><author>tracker_w</author><pubDate>Fri, 09 Oct 2020 20:12:02 +0800</pubDate><description><![CDATA[本篇我们专注invokevirtual这一条指令，先通过简单粗暴的方式实现指令的功能，然后探究如何通过著名的虚方法表(Virtual Method Table)来进行一些优化。
指令含义
invokevirtual用于调用除静态方法、构造方法、私有方法、接口方法外的所有方法。其指令的格式为：
invokevirtual = 182 (0xb6)

Format:
invokevirtual indexbyte1 indexbyte2

Operand Stack:
..., objectref, [arg1]]></description><category></category></item><item><title><![CDATA[从JVM角度看为什么final字段可以“延迟“到构造方法中初始化]]></title><link>https://blog.csdn.net/tracker_w/article/details/108349278</link><guid>https://blog.csdn.net/tracker_w/article/details/108349278</guid><author>tracker_w</author><pubDate>Tue, 01 Sep 2020 19:42:04 +0800</pubDate><description><![CDATA[我们都知道在Java中final字段都是要在定义时完成初始化工作的，否则通不过编译。但是有一处例外，那就是对于对象的字段来说final字段可以"延迟"到构造方法，或者static {}语句块中初始化，例如下面的代码
public class FinalTest {
    private static final Object staticObj;
    private final Object noneStatic;

    static {
        staticObj = new Objec]]></description><category></category></item><item><title><![CDATA[[Golang实现JVM第六篇]实现Native方法]]></title><link>https://blog.csdn.net/tracker_w/article/details/108202372</link><guid>https://blog.csdn.net/tracker_w/article/details/108202372</guid><author>tracker_w</author><pubDate>Mon, 24 Aug 2020 16:39:45 +0800</pubDate><description><![CDATA[首先需要明确几个问题。
没有Native方法JVM什么也做不了
可能很多人认为native方法是Java里的禁区，使用本地方法会牺牲可移植性，而且还会有额外开销，貌似几乎没有程序员会在实际项目中写本地方法，这玩意就是个很冷门的东西。其实这种看法是错误的，哪怕一个Hello Word程序都是要严重依赖于本地方法的。在JDK中，你会发现任何涉及到I/O、线程操作的类，层层追踪源码后最终都能找到一个对应的native调用，真正把Hello World打印到控制台的正是这些native方法。而用于启动线程的Thre]]></description><category></category></item><item><title><![CDATA[[Golang实现JVM第五篇]静态方法调用的实现]]></title><link>https://blog.csdn.net/tracker_w/article/details/107207722</link><guid>https://blog.csdn.net/tracker_w/article/details/107207722</guid><author>tracker_w</author><pubDate>Wed, 08 Jul 2020 15:50:47 +0800</pubDate><description><![CDATA[一直以来又长又臭的调用链简直就是Java语言的标志性特色，方法调用可谓是Java世界里表达一切逻辑的基石。现在我们终于具备了实现它的基础。
JVM中的5条方法调用指令
在JVM中触发方法调用的指令有5条，分别是：

invokestatic

调用静态方法

invokespecial

调用构造方法

invokeinterface

调用接口方法

invokevirtual

调用对象方法

invokedynamic

jdk1.7中引入，给动态语言预留的调用指令。指令的第一个参数不再是代表方法符号]]></description><category></category></item><item><title><![CDATA[[Golang实现JVM第四篇] 整数加法和条件判断指令的实现]]></title><link>https://blog.csdn.net/tracker_w/article/details/107083202</link><guid>https://blog.csdn.net/tracker_w/article/details/107083202</guid><author>tracker_w</author><pubDate>Thu, 02 Jul 2020 14:11:37 +0800</pubDate><description><![CDATA[在上一篇中我们实现了一个能跑的解释器，支持了一些基本的栈操作指令。现在我们就可以开始实现"有点用"的数学运算和条件判断了。
github: https://github.com/wanghongfei/mini-jvm
局部变量表、程序计数器
由于JVM字节码是基于栈的指令集，因此一切操作都是以栈为基础的，也就是说计算1+1,那需要先在栈中压入两个1然后进行计算，如果是对象方法调用，那么对象的引用、方法参数都会事先被压入栈中。除栈外还有一个跟执行相关的重要结构就是局部变量表(Local Variable T]]></description><category></category></item><item><title><![CDATA[[Golang实现JVM第三篇] 解释器雏形]]></title><link>https://blog.csdn.net/tracker_w/article/details/106765801</link><guid>https://blog.csdn.net/tracker_w/article/details/106765801</guid><author>tracker_w</author><pubDate>Mon, 15 Jun 2020 16:43:35 +0800</pubDate><description><![CDATA[在上一篇中我们已经完成了class文件的解析工作，虽然没有解析所有的属性，但是已经足够支持一些基本的算法题Java代码编译生成的class文件了。有了这一步，日后如果遇到新的特性需要支持，只需缺哪补哪，补上对应属性的解析逻辑就可以了。下一步就是实现一个基本的执行引擎，即解释器，并且支持基本的栈操作相关的指令，比如iconst_x, istore_x, bipush等。
基于栈的指令集和基于寄存器的指令集
JVM字节码是一套基于栈的指令集，也就是说操作数栈是一切计算的基本容器，大部分指令都是围绕着操作数栈展开]]></description><category></category></item><item><title><![CDATA[[Golang实现JVM第二篇]解析class文件是万里长征第一步]]></title><link>https://blog.csdn.net/tracker_w/article/details/106375894</link><guid>https://blog.csdn.net/tracker_w/article/details/106375894</guid><author>tracker_w</author><pubDate>Wed, 27 May 2020 10:40:10 +0800</pubDate><description><![CDATA[正确解析class文件是万里长征第一步。本篇我们会全程使用golang完成class文件的解析工作。
数据类型
JVM的class文件完全是二进制文件，最小单位是字节，也有数据类型，但都是字节的整数倍（废话）。规范中class文件一共有两类数据，一种是无符号整数，一种是表。无符号整数一共有u1,u2, u4, u8四种类型，分别表示8bit, 16bit, 32bit, 64bit的无符号整数。表则是无符号整数的集合，class文件中在出现表之前都会先跟着一个u2类型的长度数据，表名后面表的总长度，这样才能]]></description><category></category></item><item><title><![CDATA[【用Golang实现JVM第一篇】知识准备&前言]]></title><link>https://blog.csdn.net/tracker_w/article/details/106356698</link><guid>https://blog.csdn.net/tracker_w/article/details/106356698</guid><author>tracker_w</author><pubDate>Tue, 26 May 2020 15:08:28 +0800</pubDate><description><![CDATA[学习JVM最好的方法，就是实现它，没有之一。
对JVM感兴趣的朋友可能会去主动寻找讲解JVM的书，比如《深入理解JVM》、《Java虚拟机规范》、《虚拟机的设计与实现》，但是这些书都是定性讲解，多数人看过以后对不少概念还是会很模糊，其根本原因就是我们无法只根据定义在脑袋里想象出具体用代码应该怎么实现，就会有一种空中楼阁的感觉。既然虚拟机规范都是公开的，为什么我们不尝试着去实现一个能跑就行的JVM呢？
方法论：将复杂问题化解为简单问题的集合
国外有一本著名的操作系统教材，叫作《Operating System]]></description><category></category></item><item><title><![CDATA[Go使用chromedp库操作headless-chrome爬取"JS画出来的"网站]]></title><link>https://blog.csdn.net/tracker_w/article/details/106021625</link><guid>https://blog.csdn.net/tracker_w/article/details/106021625</guid><author>tracker_w</author><pubDate>Sat, 09 May 2020 16:08:52 +0800</pubDate><description><![CDATA[随着类似Vue、Angular这类通过JS将web页面"画"出来的前端框架的流行，爬取网页不再像以前那样随便发个GET请求，解析HTML就能搞定了。对于使用这类框架制作的SPA(Single Page Web Application)网站来说，必须使用一个全功能浏览器将JS脚本执行一遍才能获得想要的数据，除此之外别无他法。这里我们介绍如何使用Go语言的chromedp库来操作headless-chrome模拟浏览器操作，然后抓取网页数据的方案。
"无头"Chrome与远程调式协议
所谓headless-ch]]></description><category></category></item><item><title><![CDATA[使用Kafka时一定要注意防止消费速度过慢触发rebalance而导致的重复消费]]></title><link>https://blog.csdn.net/tracker_w/article/details/105281035</link><guid>https://blog.csdn.net/tracker_w/article/details/105281035</guid><author>tracker_w</author><pubDate>Thu, 02 Apr 2020 22:26:06 +0800</pubDate><description><![CDATA[在Java应用中，我们往往会使用spring-kafka组件简单的设置一下group_id, topic就开始消费消息了，其实这样会埋下巨大的安全隐患，即当消费速度过慢时有可能会触发rebalance, 这批消息被分配到另一个消费者，然后新的消费者还会消费过慢，再次rebalance, 这样一直恶性循环下去。发生这种情况最明显的标志就是日志里能看到CommitFailedException异常，然...]]></description><category></category></item><item><title><![CDATA[业务系统如何正确实现防重名功能]]></title><link>https://blog.csdn.net/tracker_w/article/details/104744295</link><guid>https://blog.csdn.net/tracker_w/article/details/104744295</guid><author>tracker_w</author><pubDate>Mon, 09 Mar 2020 00:25:17 +0800</pubDate><description><![CDATA[常见但是错误的实现
在业务系统中防重名是一个非常普遍的需求，例如用户注册时不允许用户名重复、已登录用户不可以在自己的账号范围内创建同名的某种实体等。很多人在实现的时候都是简单的先判断名字是否重复，如果没有则执行插入操作，如下：
    public void register(User user) {
        // 判断是否重复 (1)
        if (userMapper.sel...]]></description><category></category></item><item><title><![CDATA[Go1.14(即将发布)中的性能改进]]></title><link>https://blog.csdn.net/tracker_w/article/details/104489094</link><guid>https://blog.csdn.net/tracker_w/article/details/104489094</guid><author>tracker_w</author><pubDate>Tue, 25 Feb 2020 01:20:47 +0800</pubDate><description><![CDATA[Go1.14即将于2020年2月底发布，这个版本有一些值得注意的性能改进，如下：

defer

跟正常的函数调用相比，defer几乎已经没有额外的开销了。你可以在对性能极度敏感的代码中放心的使用defer了。

调度器

Goroutine支持真正意义上的抢占式调度了。我们知道在老版本中，goroutine只有当遇到I/O操作、管道/同步操作或者用户主动调用了runtime.Gosched()时...]]></description><category></category></item><item><title><![CDATA[Go Web系统中的错误处理(可能是最佳)实践]]></title><link>https://blog.csdn.net/tracker_w/article/details/103611889</link><guid>https://blog.csdn.net/tracker_w/article/details/103611889</guid><author>tracker_w</author><pubDate>Thu, 19 Dec 2019 11:47:36 +0800</pubDate><description><![CDATA[文章目录不要直接无脑返回error使用runtime.Caller()添加代码位置信息使用错误嵌套保存原始错误错误的分类
在讨论所有的错误处理实践之前首先要接受一个事实，那就是每调用一个函数/方法都要检查一下返回值中的err是否为空的操作是无法避免的，这可能是很多从Java转过来的开发者们除语法习惯以外最大的不适应。当然Go里也可以通过panic来模拟抛出"异常"然后中断执行流跳转到错误处理函数的...]]></description><category></category></item><item><title><![CDATA[数据库事务中不可重复读与幻读的区别]]></title><link>https://blog.csdn.net/tracker_w/article/details/103148300</link><guid>https://blog.csdn.net/tracker_w/article/details/103148300</guid><author>tracker_w</author><pubDate>Tue, 19 Nov 2019 18:21:22 +0800</pubDate><description><![CDATA[开门见山
可重复读仅能保证再次执行同样的查询时，先前返回【过】的结果一定跟之前一样，而不保证会不会多出别的记录。如果返回了之前没有出现过的记录，就是幻读。
隔离级别
数据库事务的四种隔离级别相信现在已经烂大街了，但是发现很多文章都没有解释清楚不可重复读non-repeatable read与幻读phantom的区别，所以这里总结明确一下。


读未提交(Read Uncommitted)
这个非常...]]></description><category></category></item><item><title><![CDATA[Netty对零拷贝(Zero Copy)三个层次的实现]]></title><link>https://blog.csdn.net/tracker_w/article/details/102756099</link><guid>https://blog.csdn.net/tracker_w/article/details/102756099</guid><author>tracker_w</author><pubDate>Sat, 26 Oct 2019 14:13:47 +0800</pubDate><description><![CDATA[首先我们来看一下维基百科对零拷贝给出的定义：

零拷贝描述了一种计算机中的操作，即CPU在执行某项任务时不需要先将数据从内存中的一个位置移动到另一个位置就可以完成操作，从而节省了CPU时钟周期和内存带宽。

从上面的描述可以看出，其实只要是节省了一次或多次数据的复制就可以称之为零拷贝了，这其实是一种广义的定义。在Netty中对于零拷贝有三个层次的实现，我们就一条条分析一下。
避免数据流经用户空间
...]]></description><category></category></item><item><title><![CDATA[Go中方法接收者是指针类型和值类型的根本区别, 看这一篇就足够了]]></title><link>https://blog.csdn.net/tracker_w/article/details/98211666</link><guid>https://blog.csdn.net/tracker_w/article/details/98211666</guid><author>tracker_w</author><pubDate>Fri, 02 Aug 2019 16:48:34 +0800</pubDate><description><![CDATA[要理解使用指针接收者和使用值接收者的根本区别只需要明确一点就够了：它们的方法名是不一样的。
方法名
我们拿Man和Woman两个简单的结构体举例：
type Man struct {
}
type Woman struct {
}

我们分别使用指针接收者和值接收者给它们添加一个Say()方法:
// Say()方法的全名为(*Man).Say()
// 即只有指针类型*Man才有Say()方法
...]]></description><category></category></item><item><title><![CDATA[Git工作流: 主干开发tag上线]]></title><link>https://blog.csdn.net/tracker_w/article/details/97629622</link><guid>https://blog.csdn.net/tracker_w/article/details/97629622</guid><author>tracker_w</author><pubDate>Mon, 29 Jul 2019 11:16:12 +0800</pubDate><description><![CDATA[使用git的朋友应该都熟悉一些常见的工作流，比如主干开发分支上线和分支开发主干上线。前者是指在master分支永远是开发版的最新代码，而分支上则是当前线上部署的代码，后者反之。这里给大家介绍一个我个人非常习惯的流程：主干开发，Tag上线。
只用master分支，上线打tag
所谓Tag上线是指我们全程都只有一个master分支，所有代码都向master提交，当上线的时候我们会在当前版本上打一个ta...]]></description><category></category></item></channel></rss>