Ant编译导致的Java bug问题

最近在开发机装了jenkins做持续集成和自动部署上线。使用ant脚本做编译打包。遇到了一个问题,分享下。
本质上这个问题不是ant的问题,但在平常使用中很容易被忽略掉,导致排查问题浪费时间。

举个例子,场景是这样的,在Spring MVC中我们常用到注解来简化代码,以Controller为例,有两种写法:

  1. 写法1

    1
    2
    3
    4
    5
    @RequestMapping(method = RequestMethod.POST, value = "/modify")
    public String modify(HttpServletRequest request,
    @RequestParam("name") String name,
    ModelMap model) {
    }
  2. 写法2

    1
    2
    3
    4
    5
    @RequestMapping(method = RequestMethod.POST, value = "/modify")
    public String modify(HttpServletRequest request,
    String name,
    ModelMap model) {
    }

Read More

OpenSSL的严重bug

OpenSSL今天曝出一严重Bug,牵连的版本非常多,多个linux发行版中招。

Bug详情

OpenSSL v1.0.1到1.0.1f中发现了一个非常严重bug(CVE-2014-0160),该bug允许攻击者读取存在bug的系统的64kb处理内存,暴露加密流量的密钥,用户的名字和密码,以及访问的内容。攻击者可以利用该bug窃听通信,直接从服务和用户窃取数据。OpenSSL已经发布了1.0.1g修正bug,Debian发行版也在半小时修复了bug,Fedora发布了一个权宜的修正方案。

该bug是在2011年引入到OpenSSL中,使用OpenSSL 0.9.8的发行版不受影响,但Debian Wheezy、Ubuntu 12.04.4、 Centos 6.5、Fedora 18、SuSE 12.2、OpenBSD 5.4、FreeBSD 8.4和NetBSD 5.0.2之后的版本都受到影响。如果你运行存在该bug的系统,那么最好废除所有密钥。【摘自OpenSSL严重bug允许攻击者读取64k内存,Debian半小时修复

查看系统OpenSSL情况

openssl version -a命令查看版本,如果发现版本号刚好处于v1.0.1到v1.0.1f间,恭喜!躺着中枪的感觉。赶紧升级版本吧!

Read More

一次坑死爹的Java项目tomcat7部署异常

刚接手一台开发机,已经使用过比较久的时间,可能前后经历的人比较多,所以环境比较杂,不熟悉。场景是这样的,我的本地环境是OSX10.9的Java7,代码都在本地开发,已经部署测试完毕,使用的是tomcat7版本。然后eclipse使用ant编译成war包后准备服务器部署,问题来了。

问题1

部署后启动tomcat,程序不能运行,Unsupported major.minor version 51.0,大体意思是提示编译问题,然后查看开发机Java环境,发现是1.6,本地修改eclipse的Java Compiler的Compiler compliance level为1.6即可。

Read More

Sublime text2编译运行node.js程序

安装插件

1
git clone git://github.com/tanepiper/SublimeText-Nodejs.git ~/Library/Application\ Support/Sublime\ Text\ 2/Packages/Nodejs

配置

/private/var/root/Library/Application Support/Sublime Text 2/Packages下修改连个配置文件:

Nodejs.sublime-settings:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
// save before running commands
"save_first": true,
// if present, use this command instead of plain "node"
// e.g. "/usr/bin/node" or "C:\bin\node.exe"
"node_command": "/usr/local/bin/node",
// Same for NPM command
"npm_command": "/usr/local/bin/npm",
// as 'NODE_PATH' environment variable for node runtime
"node_path": false,

"expert_mode": false,

"ouput_to_new_tab": false
}

Nodejs.sublime-build:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"cmd": ["/usr/local/bin/node", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.js",
"shell":false,
"encoding": "utf8",
"windows":
{
"cmd": ["taskkill /F /IM node.exe & node", "$file"]
}
,

"linux":
{
"cmd": ["killall node; node", "$file"]
}

}

shell配为false

运行

ctrl+b即可,或者右键.

Java synchronized

小记

  • synchronized可作用于instance变量、对象引用、static函数和class上。
  • 每个对象只有一个锁(lock)与之相关联。每一个类也对应一把锁,因此也可将类的静态成员函数声明为 synchronized,以控制其对的静态成员变量的访问,注意这里会锁在“类”上,而不是实例上。

  • synchronized:三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,虽然这些同步块处在不同的方法中,但由于是同步到同一个对象(如synchronized (this)),所以对它们的方法依然是互斥的。 但对于以下同步到三个不同的对象,则对临界资源的访问是独立的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Object o1 = new Object();
    Object o2 = new Object();

    void m1(){
    synchronized (this) {
    //..
    }
    }
    void m2(){
    synchronized (o1) {
    //..
    }
    }
    void m3(){
    synchronized (o2) {
    //..
    }
    }

synchronized使用

  • synchronized method(){} 对该类的同一个对象来说,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法。而不同的对象则是互不干扰的。
  • synchronized static method{} 对该类的所有对象起作用。
  • synchronized关键字是不能继承的

synchronized实现原理

待续。

Java异常处理

这篇文章主要用来对java异常处理一些容易模糊的概念做梳理。接受一个教训,有些基础理论知识、专业名词说不定哪天就会用到,还是多记一点的好。

概念

Thorwable类是所有异常和错误的超类,有两个子类Error和Exception。Error是程序无法处理的错误,比如OutOfMemoryError、ThreadDeath等。

运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等。
这些异常是非检查异常,程序中可以选择捕获处理,也可以不处理。
这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。处理RuntimeException的原则是:如果出现,那么一定是程序的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。

非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。
从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。
如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。

处理原则

  • 能处理就早处理,抛出不去还不能处理的就想法消化掉或者转换为RuntimeException处理。
  • 对于检查异常,如果不能行之有效的处理,还不如转换为RuntimeException抛出。这样也让上层的代码有选择的余地――可处理也可不处理。
  • 对于一个应用系统来说,应该有自己的一套异常处理框架,这样当异常发生时,也能得到统一的处理风格,将优雅的异常信息反馈给用户。

Read More

分布式系统中的ID生成

问题

在分布式系统中常遇到ID生成问题:

  • 场景1,在分库分表中需要保证某类ID唯一,这样使用主键自增的策略就不再合适
  • 场景2,需要某类ID需要具有同一特性来标识

诸如此类。

方案

有很多解决方案,比如

  1. 基于数据库主键自增策略(及其变种,如分片生成以提高效率、分库分表生成以解决单点问题等)
  2. UUID(简单但比较丑陋,生成的ID无规律,也有方案是基于UUID,但更简短
  3. 基于MongoDB的id策略
  4. DIY的ID(以不同用途的字符组装到一起,然后做编码转换以满足需要)

这里介绍一种方案4的实现,基本思想源于twitter的Snowflake方案,该实现可提供高性能、低延迟、高可用的ID生成。

Read More

Merkle-Hash-Tree

Merkle Tree, 也叫 Hash Tree. 它是Ralph Merkle在1979年创造的。据说最早Merkle创造Merkle Tree(MT)的目的是为了生成Lamport签名,一种一次性的数字签名.

上图(来自Wikipedia)给出了一个二进制的哈希树(二叉哈希树, 较常用的tiger hash tree也是这个形式). 据称哈希树经常应用在一些分布式系统或者分布式存储中的反熵机制(Anti-entropy),也有称做去熵的.这些应用包括 Amazon的Dynamo 还有Apache的Cassandra数据库, 通过去熵可以去做到各个不同节点的同步, 即保持各个节点的信息都是同步最新.

哈希树的特点很鲜明: 叶子节点存储的是数据文件,而非叶子节点存储的是其子节点的哈希值(称为MessageDigest) 这些非叶子节点的Hash被称作路径哈希值, 叶子节点的Hash值是真实数据的Hash值. 因为使用了树形结构, MT的时间复杂度为 O(logn)
比如下图中, 我们如果使用SHA1算法来做校验值, 比如数据块8对应的哈希值是$H23$, 则按照这个路径来看应该有

1
2
3
4
H11=SHA1(H23∥H24)
H5=SHA1(H11∥H12)
H2=SHA1(H5∥H6)
H0=SHA1(H1∥H2)

其中$\parallel$是表联接的意思.

应用举例

BitTorrent中应用

在BT中, 通常种子文件中包含的信息是Root值, 此外还有文件长度、数据块长等重要信息. 当客户端下载数据块8时,在下载前,它将要求peer提供校验块8所需的全部路径哈希值:H24、H12、H6和H1. 下载完成后, 客户端就会开始校验, 它先计算它已经下载的数据块8的Hash值23, 记做 H23′ , 表示尚未验证. 随后会按照我在上一小节中给出的几个公式, 来依次求解 直到得到H0′ 并与H0做比较, 校验通过则下载无误. 校验通过的这些路径哈希值会被缓存下来, 当一定数量的路径哈希值被缓存之后,后继数据块的校验过程将被极大简化。此时我们可以直接利用校验路径上层次最低的已知路径哈希值来对数据块进行部分校验,而无需每次都校验至根哈希值H0.

Amazon Dynamo中同步

在Dynamo中,每个节点保存一个范围内的key值,不同节点间存在有相互交迭的key值范围。在去熵操作中,考虑的仅仅是某两个节点间共有的key值范围。MT的叶子节点即是这个共有的key值范围内每个key的hash,通过叶子节点的hash自底向上便可以构建出一颗MT。Dynamo首先比对MT根处的hash,如果一致则表示两者完全一致,否则将其子节点交换并继续比较的过程, 知道定位到有差异的数据块. 这种同步方式在分布式中有着节省网络传输量的优点.

引用:

http://en.wikipedia.org/wiki/Hash_tree
http://en.wikipedia.org/wiki/Lamport_signature
http://blog.csdn.net/starxu85/article/details/3859011
http://ultimatearchitecture.net/index.php/2010/09/12/merkle-tree/
http://www.public.asu.edu/~rzhang46/
http://yishanhe.net/wiki/Secure-topk-query.html
http://www.bittorrent.org/beps/bep_0030.html
https://www.usenix.org/conference/osdi12/secure-offline-data-access-using-commodity-trusted-hardware

发布一个轻型文件编辑器 - lincell,一行命令创建IDE

1. 前言

刚发布一个叫做lincell的模块,第一版放出来遛遛,可以通过npm安装使用。等下一版本会对代码做大的更改,不过使用者不用管,除非你要看代码,github地址在这里,项目页面在这里

它的前端是通过nide改造的,我对整个代码做了较大更改,后面计划的功能更会改得面目全非,所以也没有fork,只是重开了一个项目命名为lincell,本来我更中意linc,但npm上的坑儿已经被占了,无奈。

为什么要开发lincell:

  • nide作者很懒,都一年多不维护了,估计我以后也会很懒
  • nide不支持windows,有人问那你为什么需要windows,好吧,很苦逼的是我有一台windows主机要维护;还有个原因是,我在windows上做开发的时候也想用它,毕竟它足够轻量
  • nide依赖的node和库版本都太老,我有喜新厌旧强迫症
  • 后台基于Event的处理有bug
  • 我特别想要的功能它没有,比如上传下载,代码折叠,多标签页显示,markdown预览等等

分享publish到npm时的一个

  • 问题:平常一般用linux开发,所以不会遇到文件格式或是编码的问题,但这次lincell的大部分代码是在windows上写的,所以发布到npm上后,在windows上安装使用都没问题,但在linux上就错了(找不到文件)
  • 解决:在程序入口文件app.js的头部添加#!/usr/bin/env node让linux知道用node去运行它,然后把文件格式改为UNIX

Read More