java aio 编程

Java NIO (JSR 51)定义了Java new I/O API,提案2000年提出,2002年正式发布。 JDK 1.4起包含了相应的API实现。
JAVA NIO2 (JSR 203)定义了更多的 New I/O APIs, 提案2003提出,直到2011年才发布, 最终在JDK 7中才实现。
JSR 203除了提供更多的文件系统操作API(包括可插拔的自定义的文件系统), 还提供了对socket和文件的异步 I/O操作。 同时实现了JSR-51提案中的socket channel全部功能,包括对绑定, option配置的支持以及多播multicast的实现。

当前很多的项目还停留在JAVA NIO的实现上, 对JAVA AIO(asynchronous I/O)着墨不多。 本文整理了一些关于JAVA AIO的介绍,以及netty对AIO的支持。
以下内容只针对socket的I/O操作, 不涉及对文件的处理。

阅读全文

Java 8 Lambda 揭秘

再了解了Java 8 Lambda的一些基本概念和应用后, 我们会有这样的一个问题: Lambda表达式被编译成了什么?。 这是一个有趣的问题,涉及到JDK的具体的实现。 本文将介绍OpenJDK对Lambda表达式的转换细节, 读者可以了解Java 8 Lambda表达式背景知识。

阅读全文

Java 8 默认方法和多继承

以前经常谈论的Java对比c++的一个优势是Java中没有多继承的问题。 因为Java中子类只能继承(extends)单个父类, 尽管可以实现(implements)多个接口,但是接口中只有抽象方法,方法体是空的,没有具体的方法实现,不会有方法冲突的问题。

这些都是久远的说法了,自从今年Java 8发布后, 接口中也可以定义方法了(default method)。 之所以打破以前的设计在接口中
增加具体的方法, 是为了既有的成千上万的Java类库的类增加新的功能, 且不必对这些类重新进行设计。 比如, 只需在Collection接口中
增加default Stream<E> stream(), 相应的SetList接口以及它们的子类都包含此的方法, 不必为每个子类都重新copy这个方法。

这是一个折衷的设计,带来的问题就是为Java引入了多继承的问题。 我们知道, 接口可以继承接口, 类可以继承类和实现接口。 一旦继承的类和实现的接口中有
相同签名的方法, 会出现什么样的状况呢? 本文将探讨各种情况的多继承, 以便能清楚的理解Java多继承的规则。

阅读全文

Java 8函数式接口functional interface的秘密

函数式接口(Functional Interface)是Java 8对一类特殊类型的接口的称呼。 这类接口只定义了唯一的抽象方法的接口(除了隐含的Object对象的公共方法), 因此最开始也就做SAM类型的接口(Single Abstract Method)。

为什么会单单从接口中定义出此类接口呢? 原因是在Java Lambda的实现中, 开发组不想再为Lambda表达式单独定义一种特殊的Structural函数类型,称之为箭头类型(arrow type), 依然想采用Java既有的类型系统(class, interface, method等), 原因是增加一个结构化的函数类型会增加函数类型的复杂性,破坏既有的Java类型,并对成千上万的Java类库造成严重的影响。 权衡利弊, 因此最终还是利用SAM 接口作为 Lambda表达式的目标类型。

JDK中已有的一些接口本身就是函数式接口,如Runnable。 JDK 8中又增加了java.util.function包, 提供了常用的函数式接口。

函数式接口代表的一种契约, 一种对某个特定函数类型的契约。 在它出现的地方,实际期望一个符合契约要求的函数。 Lambda表达式不能脱离上下文而存在,它必须要有一个明确的目标类型,而这个目标类型就是某个函数式接口。

阅读全文

Java位操作指南

原码,反码和补码

这个是计算机的基础知识了。

+3的原码为00000011
-3的原码为10000011
第一位是符号位。

+3的反码为00000011
-3的反码为11111100
正数的反码是其本身,负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

+3的补码为00000011
-3的补码为11111101
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

使用补码可以将减法变为加法,而且0的问题也会解决。

Java中使用补码的格式保存byte,short,int,long类型的数据。 ( two's complement integer.)

位操作符

  • & 与。 按补码的每一位进行与操作。
  • | 或。 按补码的每一位进行与操作。
  • ^ 异或。 按补码的每一位进行与操作。
  • ~ 取反。 按补码的每一位进行与操作。
  • >> 带符号右移,高位补符号位。 正数右移一位相当于除以2。
  • >>> 无符号右移。高位补0。 正数右移一位相当于除以2。
  • << 左移,低位补0。 正数左移一位相当于乘以2。

除了~是一元操作符外其它都是二元操作符号。

阅读全文

Java Buffer编程基础

Java 1.4中在java.nio包中增加了Buffer类以及一些处理基本数据类型的子类(除了boolean型) ,用来提供为基本数据类型(primitive) 的数据提供一个容器。
何谓Buffer? Buffer 是一个线性的有限长度的特定基本数据的序列。 除了基础数据外,它还包括一些基础操作和属性, 比如capacity, limitposition

实际使用中使用特定的子类来处理数据。每个子类都定义了两套get/put的操作。

  • 相对位置操作 (Relative )。 从当前位置position读写一个或者多个元素, 并position增加相应的数值。 如果一个get请求的数据超过了limit的位置,会抛出BufferUnderflowException异常。 如果一个put操作超过了limit的限制, 会抛出BufferOverflowException异常。不管上面哪种情况,没有数据被传输。
  • 绝对位置操作 (Absolute )。 显式地提供index, 不会影响position的值。 如果索引超过limit会抛出IndexOutOfBoundsException异常。

数据也可以通过Channel的I/O操作如write,read 写入或者读出。
显然, Buffer只有写入了数据才可能有意义的数据读出。

Buffer类并不是线程安全的, 使用时要特别小心, 避免多线程同时读写同一个Buffer。 万不得已, 需要为读写操作加锁。

阅读全文

使用FastJson作为JAX-RS的序列化/反序列化框架

FastJson是阿里巴巴的温少开发的一个JSON的序列化和反序列化的框架。 我前面的文章: Java序列化框架性能比较中也提到, 我使用第三方的序列化测试框架jvm-serializers表明, FastJson是最快的JSON序列化框架之一, 优于Jackson。

JAX-RS是一个Java编程语言的应用程序接口,支持按照 表象化状态转变 (REST)架构风格创建Web服务Web服务. JAX-RS使用了Java SE 5引入的Java 标注来简化Web服务客户端和服务端的开发和部署。
JAX-RS的实现包括:

  • Apache CXF,开源的Web服务框架。
  • Jersey, 由Sun提供的JAX-RS的参考实现。
  • RESTEasy,JBoss的实现。
  • Restlet,由Jerome Louvel和Dave Pawson开发,是最早的REST框架,先于JAX-RS出现。
  • Apache Wink,一个Apache软件基金会孵化器中的项目,其服务模块实现JAX-RS规范

如果项目中使用JAX-RS传递JSON格式的数据, 可以利用FastJson提高序列化的性能。 但是FastJson并没有提供JAX-RS的集成( Issue #65, Issue #138 )。

我实现了一个FastJson的JAX-RS集成框架: fastjson-jaxrs-json-provider ,可以方便在在JAX-RS项目中使用。

阅读全文

java 和netty epoll实现

Java NIO根据操作系统不同, 针对nio中的Selector有不同的实现:

所以毋须特别指定, Oracle jdk会自动选择合适的Selector。 如果想设置特定的Selector,可以属性:

1
-Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider

阅读全文