自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

王鸿飞的专栏

简书: https://www.jianshu.com/u/5267bcbeb04d CSDN也会同步更新

  • 博客(262)
  • 资源 (9)
  • 收藏
  • 关注

原创 Maven中如何跳过不支持skip参数的插件执行

我们知道,很多maven官方插件都支持skip参数,命令行指定skip=true即可跳过此插件的执行,非常方便。但是很多第三方的插件根本就不支持skip参数,无法通过命令行传参的方式跳过插件的执行。我们可以用一些非官方的方式绕过这个限制。总体思路为,将你想要跳过的插件的phase参数指定为一个不存在的phase,这样maven在执行的时候就会忽略这个插件。例如: <properties> <mvn.jarvis.skip>package</mvn.jarvis.s

2022-03-09 17:52:33 1623 1

原创 快速彻底理解字符集和字符集编码的区别

很多文章搞长篇大论大讲特讲人类为了让计算机能够准确表示各种字符的演化历史,这完全是没有必要的,几句话就能说明白。"字符集"和"字符集编码"是两回事字符集(Charset Set),仅仅是一套从【字符】到【数字】的映射字典,它只规定了应该用什么数字来标识字符,仅此而已,至于计算机在存储的时候应该用什么字节来标识,字符集是根本不管这事的。Unicode, GB2312, ASCII都属于字符集。字符集编码(Character Encoding),专门规定了字符集中的字符在计算机中应该如何存储,说白了就是怎

2021-11-07 18:35:10 444

原创 如何手动编译Apple Silicon M1版本的JavaFX SceneBuilder

用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

2021-07-03 13:15:14 642 1

原创 [Golang实现JVM第七篇]实现invokevirtual和虚方法表

本篇我们专注invokevirtual这一条指令,先通过简单粗暴的方式实现指令的功能,然后探究如何通过著名的虚方法表(Virtual Method Table)来进行一些优化。指令含义invokevirtual用于调用除静态方法、构造方法、私有方法、接口方法外的所有方法。其指令的格式为:invokevirtual = 182 (0xb6)Format:invokevirtual indexbyte1 indexbyte2Operand Stack:..., objectref, [arg1

2020-10-09 20:12:02 825

原创 从JVM角度看为什么final字段可以“延迟“到构造方法中初始化

我们都知道在Java中final字段都是要在定义时完成初始化工作的,否则通不过编译。但是有一处例外,那就是对于对象的字段来说final字段可以"延迟"到构造方法,或者static {}语句块中初始化,例如下面的代码public class FinalTest { private static final Object staticObj; private final Object noneStatic; static { staticObj = new Objec

2020-09-01 19:42:04 440

原创 [Golang实现JVM第六篇]实现Native方法

首先需要明确几个问题。没有Native方法JVM什么也做不了可能很多人认为native方法是Java里的禁区,使用本地方法会牺牲可移植性,而且还会有额外开销,貌似几乎没有程序员会在实际项目中写本地方法,这玩意就是个很冷门的东西。其实这种看法是错误的,哪怕一个Hello Word程序都是要严重依赖于本地方法的。在JDK中,你会发现任何涉及到I/O、线程操作的类,层层追踪源码后最终都能找到一个对应的native调用,真正把Hello World打印到控制台的正是这些native方法。而用于启动线程的Thre

2020-08-24 16:39:45 803

原创 [Golang实现JVM第五篇]静态方法调用的实现

一直以来又长又臭的调用链简直就是Java语言的标志性特色,方法调用可谓是Java世界里表达一切逻辑的基石。现在我们终于具备了实现它的基础。JVM中的5条方法调用指令在JVM中触发方法调用的指令有5条,分别是:invokestatic调用静态方法invokespecial调用构造方法invokeinterface调用接口方法invokevirtual调用对象方法invokedynamicjdk1.7中引入,给动态语言预留的调用指令。指令的第一个参数不再是代表方法符号

2020-07-08 15:50:47 553 2

原创 [Golang实现JVM第四篇] 整数加法和条件判断指令的实现

在上一篇中我们实现了一个能跑的解释器,支持了一些基本的栈操作指令。现在我们就可以开始实现"有点用"的数学运算和条件判断了。github: https://github.com/wanghongfei/mini-jvm局部变量表、程序计数器由于JVM字节码是基于栈的指令集,因此一切操作都是以栈为基础的,也就是说计算1+1,那需要先在栈中压入两个1然后进行计算,如果是对象方法调用,那么对象的引用、方法参数都会事先被压入栈中。除栈外还有一个跟执行相关的重要结构就是局部变量表(Local Variable T

2020-07-02 14:11:37 342

原创 [Golang实现JVM第三篇] 解释器雏形

在上一篇中我们已经完成了class文件的解析工作,虽然没有解析所有的属性,但是已经足够支持一些基本的算法题Java代码编译生成的class文件了。有了这一步,日后如果遇到新的特性需要支持,只需缺哪补哪,补上对应属性的解析逻辑就可以了。下一步就是实现一个基本的执行引擎,即解释器,并且支持基本的栈操作相关的指令,比如iconst_x, istore_x, bipush等。基于栈的指令集和基于寄存器的指令集JVM字节码是一套基于栈的指令集,也就是说操作数栈是一切计算的基本容器,大部分指令都是围绕着操作数栈展开

2020-06-15 16:43:35 424

原创 [Golang实现JVM第二篇]解析class文件是万里长征第一步

正确解析class文件是万里长征第一步。本篇我们会全程使用golang完成class文件的解析工作。数据类型JVM的class文件完全是二进制文件,最小单位是字节,也有数据类型,但都是字节的整数倍(废话)。规范中class文件一共有两类数据,一种是无符号整数,一种是表。无符号整数一共有u1,u2, u4, u8四种类型,分别表示8bit, 16bit, 32bit, 64bit的无符号整数。表则是无符号整数的集合,class文件中在出现表之前都会先跟着一个u2类型的长度数据,表名后面表的总长度,这样才能

2020-05-27 10:40:10 461

原创 【用Golang实现JVM第一篇】知识准备&前言

学习JVM最好的方法,就是实现它,没有之一。对JVM感兴趣的朋友可能会去主动寻找讲解JVM的书,比如《深入理解JVM》、《Java虚拟机规范》、《虚拟机的设计与实现》,但是这些书都是定性讲解,多数人看过以后对不少概念还是会很模糊,其根本原因就是我们无法只根据定义在脑袋里想象出具体用代码应该怎么实现,就会有一种空中楼阁的感觉。既然虚拟机规范都是公开的,为什么我们不尝试着去实现一个能跑就行的JVM呢?方法论:将复杂问题化解为简单问题的集合国外有一本著名的操作系统教材,叫作《Operating System

2020-05-26 15:08:28 683

原创 Go使用chromedp库操作headless-chrome爬取"JS画出来的"网站

随着类似Vue、Angular这类通过JS将web页面"画"出来的前端框架的流行,爬取网页不再像以前那样随便发个GET请求,解析HTML就能搞定了。对于使用这类框架制作的SPA(Single Page Web Application)网站来说,必须使用一个全功能浏览器将JS脚本执行一遍才能获得想要的数据,除此之外别无他法。这里我们介绍如何使用Go语言的chromedp库来操作headless-chrome模拟浏览器操作,然后抓取网页数据的方案。"无头"Chrome与远程调式协议所谓headless-ch

2020-05-09 16:08:52 3527

原创 使用Kafka时一定要注意防止消费速度过慢触发rebalance而导致的重复消费

在Java应用中,我们往往会使用spring-kafka组件简单的设置一下group_id, topic就开始消费消息了,其实这样会埋下巨大的安全隐患,即当消费速度过慢时有可能会触发rebalance, 这批消息被分配到另一个消费者,然后新的消费者还会消费过慢,再次rebalance, 这样一直恶性循环下去。发生这种情况最明显的标志就是日志里能看到CommitFailedException异常,然...

2020-04-02 22:26:06 7220 1

原创 业务系统如何正确实现防重名功能

常见但是错误的实现在业务系统中防重名是一个非常普遍的需求,例如用户注册时不允许用户名重复、已登录用户不可以在自己的账号范围内创建同名的某种实体等。很多人在实现的时候都是简单的先判断名字是否重复,如果没有则执行插入操作,如下: public void register(User user) { // 判断是否重复 (1) if (userMapper.sel...

2020-03-09 00:25:17 1907 1

原创 Go1.14(即将发布)中的性能改进

Go1.14即将于2020年2月底发布,这个版本有一些值得注意的性能改进,如下:defer跟正常的函数调用相比,defer几乎已经没有额外的开销了。你可以在对性能极度敏感的代码中放心的使用defer了。调度器Goroutine支持真正意义上的抢占式调度了。我们知道在老版本中,goroutine只有当遇到I/O操作、管道/同步操作或者用户主动调用了runtime.Gosched()时...

2020-02-25 01:20:47 968

原创 Go Web系统中的错误处理(可能是最佳)实践

文章目录不要直接无脑返回error使用runtime.Caller()添加代码位置信息使用错误嵌套保存原始错误错误的分类在讨论所有的错误处理实践之前首先要接受一个事实,那就是每调用一个函数/方法都要检查一下返回值中的err是否为空的操作是无法避免的,这可能是很多从Java转过来的开发者们除语法习惯以外最大的不适应。当然Go里也可以通过panic来模拟抛出"异常"然后中断执行流跳转到错误处理函数的...

2019-12-19 11:47:36 1181

原创 数据库事务中不可重复读与幻读的区别

开门见山可重复读仅能保证再次执行同样的查询时,先前返回【过】的结果一定跟之前一样,而不保证会不会多出别的记录。如果返回了之前没有出现过的记录,就是幻读。隔离级别数据库事务的四种隔离级别相信现在已经烂大街了,但是发现很多文章都没有解释清楚不可重复读non-repeatable read与幻读phantom的区别,所以这里总结明确一下。读未提交(Read Uncommitted)这个非常...

2019-11-19 18:21:22 592

原创 Netty对零拷贝(Zero Copy)三个层次的实现

首先我们来看一下维基百科对零拷贝给出的定义:零拷贝描述了一种计算机中的操作,即CPU在执行某项任务时不需要先将数据从内存中的一个位置移动到另一个位置就可以完成操作,从而节省了CPU时钟周期和内存带宽。从上面的描述可以看出,其实只要是节省了一次或多次数据的复制就可以称之为零拷贝了,这其实是一种广义的定义。在Netty中对于零拷贝有三个层次的实现,我们就一条条分析一下。避免数据流经用户空间...

2019-10-26 14:13:47 815 1

原创 Go中方法接收者是指针类型和值类型的根本区别, 看这一篇就足够了

要理解使用指针接收者和使用值接收者的根本区别只需要明确一点就够了:它们的方法名是不一样的。方法名我们拿Man和Woman两个简单的结构体举例:type Man struct {}type Woman struct {}我们分别使用指针接收者和值接收者给它们添加一个Say()方法:// Say()方法的全名为(*Man).Say()// 即只有指针类型*Man才有Say()方法...

2019-08-02 16:48:34 1835 3

原创 Git工作流: 主干开发tag上线

使用git的朋友应该都熟悉一些常见的工作流,比如主干开发分支上线和分支开发主干上线。前者是指在master分支永远是开发版的最新代码,而分支上则是当前线上部署的代码,后者反之。这里给大家介绍一个我个人非常习惯的流程:主干开发,Tag上线。只用master分支,上线打tag所谓Tag上线是指我们全程都只有一个master分支,所有代码都向master提交,当上线的时候我们会在当前版本上打一个ta...

2019-07-29 11:16:12 1795

原创 用Go写业务系统需要制造哪些轮子?

如果之前主要是用Java做业务系统 ,那么想用go重写的话还是比较痛苦的,最主要的原因就是你会发现要啥没啥,需要自己重写(造轮子)。下面列举了一些需要施工的基础设施。错误处理在Java中,只要你没有刻意的使用4参数的Exception构造方法去定义自己的异常类,那么默认情况下都是会记录调用栈的,这样基本上就能马上定位到事故第一现场,排查效率很高。Go则不然,如果使用默认的error机制,那么在...

2019-07-26 18:15:07 708

原创 Vert.x + Protobuf二进制协议解析

这一期介绍如何解析二进制私有协议。先说几句题外话,就是绝大多数情况下,可能根本用不着使用私有二进制协议,除非你的业务对性能极其敏感,否则HTTP足矣。协议我们的协议非常简单,先是一个4字节的整数表示数据长度,然后紧接着就是protobuf序列化后的字节数组。proto定义如下:syntax = "proto2";package cn.fh.vertx.demo.proto;optio...

2019-06-26 11:33:46 2546

原创 Java异常处理使用Throwable而不是Exception

线上问题近期在线上系统中遇到了一个奇怪的问题,某个请求处理失败了,但是日志里没有任何错误信息,catch(Exception e) {}代码块根本没有执行,因此直接跳过了错误处理逻辑,但是finally{}块却执行了。根据此现象我们推测出很可能是代码块抛出了非Exception子类的异常。果然,将catch Exception改为catch Throwable后, 日志中出现了java.lang...

2019-06-25 10:24:02 2759

原创 Vert.x与Netty的区别

虽然Vert.x是基于Netty的更高级封装,但它们解决的问题是不太一样的。可以认为Vert.x是Netty的超集,它利用Netty的Eventloop为开发者提供了更友好的编程模型。Netty解决了如何支撑大量连接的问题Netty作为一个网络I/O工具,使用起来随时都能清晰的感受到你在操作网络,在操作字节等这些与业务不太相关的东西。很明显,Netty解决的同高吞吐的网络I/O问题,而不是编程...

2019-06-18 15:08:31 12004

原创 不推荐使用Netty自带连接池ChannelPool

首先,网上关于Netty自带连接池ChannelPool的文章很少,推测一下原因可能是因为大家使用Netty时多数都是做为服务端来应用,因此基本上用不到连接池。但是如果你使用Netty封装一个HTTP客户端那就必须考虑Channel池了。不推荐使用内置ChannelPool的原因如下:没有健康检查机制如果server端关闭了连接,那么池中的某个channel会无效,由于缺乏健康检测,这个无...

2019-06-10 18:34:59 4074 4

原创 Eureka, Client, Ribbon之间的缓存和服务实时上下线实现思路分析

在使用Eureka做注册中心时,我平时遇到的最不爽问题,就是无法做到实时上下线。比如,我服务已经正常下线了,为什么上游还能调通?我服务已经上线了,为什么还有等"很久"才能真正被其他服务所"发现"?其实这些都是从Eureka到Client再到Ribbion这条链路中的逐级缓存造成的。Eureka为什么要使用缓存比如,对于Eureka来说,Eureka Client获取注册更新信息时,Eureka...

2019-05-14 19:15:31 5191

原创 spring-kafka的线程模型与spring.kafka.listener.concurrency参数

在spring应用中如果需要订阅kafka消息,通常情况下我们不会直接使用kafka-client, 而是使用更方便的一层封装spring-kafka。不过,它可不是简单的封装了kafka-client, 这里面有很多需要注意的问题,比如下面这个参数:spring.kafka.listener.concurrency=3它并不像参数名那样简单,背后挺复杂的。如果你用jstack把线程dump...

2019-04-23 17:53:34 16791 12

原创 使用Vertx编写HTTP客户端

谈谈Apache的HTTP Client谈到HTTP客户端, 在Java界最有名的当属Apache HTTP Client库了。我相信绝大多数人在使用Apache HTTP Client时都是使用的同步版本,即请求发起后需要一直等待响应返回。如果你对程序的吞吐有着更高的要求,可能会尝试使用HttpAsyncClient, 但是使用起来貌似并不那么优雅,而且还有点"浪费"。不优雅指的是其API的设...

2019-04-19 12:52:00 1879

原创 使用Vert.x + SpringBoot编写业务系统

这一期文章主要为大家介绍如何将Vert.x与SpringBoot结合起来编写最最最常见的业务系统,即数据库增删改查。谈两句SpringBootSpringBoot大家都很熟了,一个快速开发框架,其最大的特点是可将Spring应用打成可执行jar包,从而不再依赖外部容器,如Tomcat。可能绝大多数人在使用SpringBoot时一定离不了嵌入式Tomcat, 从而造成了一想到SpringBoot...

2019-03-28 21:03:24 3257 2

原创 【Vert.x初体验1】4行代码实现HTTP Server

4行代码上古时代的Java程序员如果想写一个HTTP服务,需要按下面的步骤操作:编写Servlet, 实现doXXX()方法打成war包部署Tomcat将war包copy到指定目录下进行"部署"访问8080一顿操作猛如虎,旁边的小弟小妹对你佩服的五体投地。我可能只是想说一句Hello World而已,需要这么装X么?到了中古时代,事情变的更麻烦了。虽然不需要直接写servle...

2019-03-11 19:38:34 525

原创 比较两个大文本文件的差异并输出增量和减量

现有两个4G大小、按行分割、每行为50字符(大小写字母)的text文件A, B, 现在需要在有限的内存下(如2G)以B文件为基准,计算出B相对于A增加了哪些数据和减少了哪些数据,分别以added.txt和deleted.txt命名保存。要求不能使用Spark或Hadoop这样的大数据处理框架。思路:首先使用外排序算法对A, B分别按字典序排序,输出a.sorted和b.sorted两个文件,然...

2019-03-09 20:53:26 4059 1

原创 【Vert.x准备篇2】C10K问题与Reactor模式

C10K问题是1999年一个叫Dan Kegel的美国人提出的概念,其中C为concurrently, 10K指的是1万个网络连接, 结合起来意为如何能够做到并发处理1万个连接。这里首先要澄清一下,并发(concurrency)和并行(parallel)虽然都是用来描述&quot;同时&quot;干多件事的名词,但他们是有本质区别的。并发指的是CPU通过在不同的线程之间快速切换来营造出一种多个线程同时在执行的假象...

2019-03-03 01:14:04 591 1

原创 【vert.x准备篇1】同步和异步,阻塞和非阻塞概念澄清

为了能更好的理解vert.x的线程模型,我们必须要先明确几个概念:同步(Synchronous)和异步(Asynchronous),阻塞(Blocking)和非阻塞(Non-Blocking)。关于这几个名词的解释网络上也是众多纷纭,每个人说法都不太一样,但说的又似乎很有道理。其实造成这种情况的最主要原因是这四个概念并不是完全隔离、互斥的,而是相互之间有重叠。例如,当提到异步时那调用一定是非阻塞的...

2019-02-27 20:31:13 1834

原创 Filebeat实时日志监控最佳配置

在使用filebeat监控日志文件时,如果不会做任何配置的话你可能会发现一些奇怪的问题,即有时新的日志行会马上发送到目标输出地,有时候却要延迟近10s才会被发送。要解决这个问题,首先要明确filebeat中几个组件的作用和几个重要的参数的含意,如下:Input组件input组件负责监控日志文件(目录)自身的变化情况,如某文件被移动、删除了或创建了新文件,然后将这些信息提供给Harvester...

2019-02-20 11:38:25 5517

原创 Filebeat + ES + Kibana日志解析痛点解决

使用Filebeat + ES + Kibina的组合进行日志收集的一个优点就是轻量级,因为去掉了笨重的logstash, 占用资源更少。但这也引入了一个问题,即filebeat并没有logstash那样强大的日志解析能力,往往只能把整条日志当成一个整体扔到ES中。好消息是,ES从5.x版本开始引入了Ingest Node,即允许你在对文档进行索引之前进行预处理,且支持logstash的Grok语...

2019-02-19 17:25:48 13844 2

原创 从Go语言实现模板设计模式浅谈Go的抽象能力

首先抛出一个观点,那就是Go的抽象能力的确不如Java这种严格的OOP语言强。具体表现之一就是模板模式的实现。模板的实现模板模式是OOP编程中的一把神兵利器,用好了能够提高代码的复用程度,大大提高开发效率。例如,我们可以在父类中定义完成一个任务的几个步骤并分别给出一个默认实现,然后子类继承父类,子类只需要重写自己感兴趣的方法即可,剩余逻辑都可以复用父类的代码。Spring源码中就大量充斥着这样...

2018-11-25 03:08:46 1338

原创 如何裸写或利用Spring扫描出指定包下的所有类名

在很多Java框架中都有组件扫描功能,即给出一个注解,框架能够把所有标注了此注解的类找出来。这种操作的本质是给出一个名包,能获取到此包下的所有类名,然后再通过反射判断是否加了指定的注解。无论是什么框架,包括Spring, 完成这个功能底层都是用的ClassLoader.getResources()或ClassLoader.getSystemResources()方法实现的,即先找出指定classp...

2018-09-30 16:16:55 7098

原创 Java异常(exception)性能优化

在Java中,构造异常对象是”十分”耗时的,其原因是在默认情况下,创建异常对象时会调用父类Throwable的fillInStackTrace()方法生成栈追踪信息,JDK中的源码如下:public synchronized Throwable fillInStackTrace() { if (stackTrace != null || backtr...

2018-09-11 15:42:48 5173 4

原创 @FeignClient同一个name使用多个配置类的解决方案

Feign有一个局限性,即对于同一个service-id只能使用一个配置类,如果有多个@FeignClient注解使用了相同的name属性,则注解的configuration参数会被覆盖。至于谁覆盖谁要看Spring容器初始化Bean的顺序。这个问题的有效解决方案是,当你需要给一个service-id配置第二个@FeignClient时,使用Feign Builder API手动创建接口代理,...

2018-09-03 15:32:27 22762 2

原创 Go FastHttp优雅关闭实现方案

使用Go开发web服务时很多情况下都会使用号称比标准库快10x的FastHttp, 但fasthttp(版本: 20180529.0.0)至今也没有提供优雅关闭的方法,默认情况下退出服务只能kill。下面谈几个实现方案。首先,要明确所谓的优雅关闭是要求我们在调用close()时要做到以下几点:拒绝接受新连接等待正在处理的请求完成,然后关闭连接关闭剩余空闲的连接要做到第一点,我们...

2018-07-31 14:52:22 3461

Go语言圣经中文HTML版

这是从gitbook上爬虫抓取下来的完整gitbook网页,体验与在线版本完全一样

2016-08-21

Spring Boot in Action英文版

详解Spring Boot微框架,目前还没有中文版本

2016-04-28

Go语言圣经英文文字版-The Go Programming Language

Go语言圣经英文文字版

2016-04-28

满江红Seam-2.0文档翻译, chm格式

满江红Seam文档翻译,seam-2.0版。英文不太好的朋友可以看这个。

2013-12-28

JavaEE 7 Tutorial (JavaEE 7 官方指南)

PDF版,英文原版。既能提高英文文档的阅读能力,又能提高技术水平。

2013-08-02

mysql JDBC驱动

mysql-connector-java-5.1.24-bin.jar

2013-06-03

mail.jar activation.jar

JavaMail开发必备包: mail.jar activation.jar

2013-04-27

简单贪吃蛇

基于控制台的贪吃蛇游戏,有需要的朋友下来看看

2012-08-22

访微软件记事本

在不使用MFC框架的情况下用API写的仿微软记事本,大家可以下来看看

2012-08-22

空空如也

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

TA关注的人

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