diff --git a/.gitignore b/.gitignore
index 0747bc77..d937c33d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,10 +3,5 @@
.classpath
*.log
target/
-vjkit/bin
-vjkit/docs
-vjkit/CHANGELOG.md
-vjmap/bin
-vjtop/bin
standard/docs/ali1.3.1.pdf
-vip-book.md
+standard/docs/vip-book.md
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 00000000..d240b9cc
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [2006-2012] [www.springside.org.cn]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index 328930f1..2f3fae13 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,30 @@
-# vjtools
-唯品会JDK 问题排查及性能调优工具
+# VJTools
+
+主力于Java的唯品会,关于Java的一些小家底。 [](https://travis-ci.org/vipshop/vjtools)
+
+
+# Java开发手册
+
+| 项目 | 描述 |
+| -------- | -------- |
+| [standard](/standard) | 唯品会Java开发手册|
+| [code formatter](/standard/formatter) | 格式化模板 |
+
+
+# 核心类库
+
+| 项目 | 描述 |
+| -------- | -------- |
+| [vjkit](/vjkit) | 关于文本,集合,并发,反射等基础功能的核心类库 |
+
+
+# Java工具集
+
+
+| 项目 | 描述 |
+| -------- | -------- |
+| [vjmap](/vjmap) | 打印堆内各分代中对象的统计信息 |
+| [vjtop](/vjtop) | 打印JVM概况及繁忙的java线程 |
+
+
+其他推荐的三方问题排查及性能调优工具包括:btrace,greys,async-profiler
diff --git a/standard/docs/chapter01.md b/standard/docs/chapter01.md
index d1d5a929..d945d981 100644
--- a/standard/docs/chapter01.md
+++ b/standard/docs/chapter01.md
@@ -89,16 +89,16 @@ private static Logger logger = Logger.getLogger(MyClass.class);
1)如果上下文很清晰,局部变量可以使用 `list` 这种简略命名, 否则应该使用 `userList` 这种更清晰的命名。
-
+
2)禁止 `a1, a2, a3` 这种带编号的没诚意的命名方式。
-
+
3)方法的参数名叫 `bookList` ,方法里的局部变量名叫 `theBookList` 也是很没诚意。
-
+
4)如果一个应用里同时存在 `Account、AccountInfo、AccountData` 类,或者一个类里同时有 `getAccountInfo()、getAccountData()`, `save()、 store()` 的函数,阅读者将非常困惑。
-
+
5) `callerId` 与 `calleeId`, `mydearfriendswithA` 与 `mydearfriendswithB` 这种拼写极度接近,考验阅读者眼力的。
----
@@ -168,4 +168,4 @@ public class B extends A {
----
-* [下一章:格式规约](chapter02.md)
\ No newline at end of file
+* [下一章:格式规约](chapter02.md)
diff --git a/standard/docs/chapter02.md b/standard/docs/chapter02.md
index e6f39557..f546555c 100644
--- a/standard/docs/chapter02.md
+++ b/standard/docs/chapter02.md
@@ -4,16 +4,16 @@
1)IDE的默认代码格式模板,能简化绝大部分关于格式规范(如空格,括号)的描述。
-
+
2)统一的模板避免不同开发者之间,因为格式不统一,产生代码合并冲突。另外,代码变更日志中因为格式不同引起的变更,也会掩盖了真正的逻辑变更。
-
+
3)设定项目组统一的行宽,建议120。
-
+
4)设定项目组统一的缩进方式(Tab或二空格,四空格均可),基于IDE自动转换。
-
+
* [VIP标准代码格式化模板](/standard/formatter)
----
@@ -40,7 +40,7 @@ if ((a == b) && (c == d))
按方法的对阅读者的关心程度排列,如果公有方法可以分成几组,私有方法也可以紧跟公有方法分组。
-
+
2)当一个类有多个构造方法,或者多个同名的重载方法,这些方法应该按顺序放置在一起。其中参数较多的方法在后面。
```java
@@ -51,7 +51,7 @@ public void foo(int a) {...}
public void foo(int a, String b) {...}
```
-
+
3)作为调用者的方法,尽量放在被调用的方法前面。
```java
diff --git a/standard/docs/chapter04.md b/standard/docs/chapter04.md
index 63799ffe..396d4763 100644
--- a/standard/docs/chapter04.md
+++ b/standard/docs/chapter04.md
@@ -48,12 +48,12 @@ try {
例外: 你不希望依赖整个对象,传播了类之间的依赖性。
-
+
2)将多个参数合并为一个新创建的逻辑对象。
例外: 多个参数之间毫无逻辑关联。
-
+
3)将函数拆分成多个函数,让每个函数所需的参数减少。
* [Sonar-107: Methods should not have too many parameters](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-107)
@@ -85,12 +85,12 @@ Validate.isTrue(length > 2, "length is %d, less than 2", length);
1) 极有可能被循环调用的方法。
-
+
2) 底层调用频度比较高的方法。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底层才会暴露问题。
比如,一般DAO层与Service层都在同一个应用中,所以DAO层的参数校验,可以省略。
-
+
3) 被声明成private,或其他只会被自己代码所调用的方法,如果能够确定在调用方已经做过检查,或者肯定不会有问题则可省略。
即使忽略检查,也尽量在方法说明里注明参数的要求,比如vjkit中的@NotNull,@Nullable标识。
@@ -162,4 +162,4 @@ a.hello(arrayList);
----
* [上一章:注释规约](chapter03.md)
-* [下一章:类设计](chapter05.md)
\ No newline at end of file
+* [下一章:类设计](chapter05.md)
diff --git a/standard/docs/chapter05.md b/standard/docs/chapter05.md
index 2557797c..a4d656d6 100644
--- a/standard/docs/chapter05.md
+++ b/standard/docs/chapter05.md
@@ -108,7 +108,7 @@ int i = ClassA.staticMethod(); // RIGHT
* [Sonar-2209: "static" members should be accessed statically](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-2209)
* [Sonar-2440: Classes with only "static" methods should not be instantiated](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-2440)
-
+
**9.2 【推荐】除测试用例,不要static import 静态方法**
静态导入后忽略掉的类名,给阅读者造成障碍。
@@ -117,7 +117,7 @@ int i = ClassA.staticMethod(); // RIGHT
* [Sonar-3030: Classes should not have too many "static" imports](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-3030) 但IDEA经常自动转换static import,所以暂不作为规则。
-
+
**9.3【推荐】尽量避免在非静态方法中修改静态成员变量的值**
```java
@@ -145,7 +145,7 @@ public void foo() {
在性能上没有区别;当内部类会被多个地方调用,或匿名内部类的长度太长,已影响对调用它的方法的阅读时,定义有名字的内部类。
-
+
2) 静态内部类 与 内部类,优先使用静态内部类:
1. 非静态内部类持有外部类的引用,能访问外类的实例方法与属性。构造时多传入一个引用对性能没有太大影响,更关键的是向阅读者传递自己的意图,内部类会否访问外部类。
@@ -172,7 +172,7 @@ public void foo() {
但getter/seter中不应有复杂的业务处理,建议另外封装函数,并且不要以getXX/setXX命名。
-
+
如果是内部类,以及无逻辑的POJO/VO类,使用getter/setter除了让一些纯OO论者感觉舒服,没有任何的好处,建议直接使用public成员变量。
例外:有些序列化框架只能从getter/setter反射,不能直接反射public成员变量。
@@ -187,19 +187,19 @@ public void foo() {
**Rule 13. hashCode和equals方法的处理,遵循如下规则:**
-
+
**13.1【强制】只要重写equals,就必须重写hashCode。 而且选取相同的属性进行运算。**
-
+
**13.2【推荐】只选取真正能决定对象是否一致的属性,而不是所有属性,可以改善性能。**
-
+
**13.3【推荐】对不可变对象,可以缓存hashCode值改善性能(比如String就是例子)。**
-
+
**13.4【强制】类的属性增加时,及时重新生成toString,hashCode和equals方法。**
-
+
* [Sonar-1206: "equals(Object obj)" and "hashCode()" should be overridden in pairs](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-1206)
----
@@ -260,4 +260,4 @@ obj.getA().getB().getC().hello();
----
* [上一章:方法设计](chapter04.md)
-* [下一章:控制语句](chapter06.md)
\ No newline at end of file
+* [下一章:控制语句](chapter06.md)
diff --git a/standard/docs/chapter06.md b/standard/docs/chapter06.md
index e762e2b5..8773c9b0 100644
--- a/standard/docs/chapter06.md
+++ b/standard/docs/chapter06.md
@@ -162,4 +162,4 @@ do-while语句要在循环最后才看到循环条件,不利于代码维护,
----
* [上一章:类设计](chapter05.md)
-* [下一章:基本类型](chapter07.md)
\ No newline at end of file
+* [下一章:基本类型](chapter07.md)
diff --git a/standard/docs/chapter07.md b/standard/docs/chapter07.md
index dea31fde..4a0148e9 100644
--- a/standard/docs/chapter07.md
+++ b/standard/docs/chapter07.md
@@ -4,13 +4,13 @@
**1.1 【推荐】需要序列化的POJO类属性使用包装数据类型**
-
+
**1.2 【推荐】RPC方法的返回值和参数使用包装数据类型**
-
+
**1.3 【推荐】局部变量尽量使用基本数据类型**
-
+
包装类型的坏处:
1)Integer 24字节,而原子类型 int 4字节。
@@ -19,7 +19,7 @@
3)包装类型还有==比较的陷阱(见规则3)
-
+
包装类型的好处:
1)包装类型能表达Null的语义。
@@ -51,7 +51,7 @@ int i = Integer.parseInt(str);
* [Sonar-2153: Boxing and unboxing should not be immediately reversed](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-2153)
-
+
**2.2 【推荐】自动拆箱有可能产生NPE,要注意处理**
```java
@@ -67,14 +67,14 @@ int i = intObject;
\==判断对象是否同一个。Integer var = ?在缓存区间的赋值(见规则1),会复用已有对象,因此这个区间内的Integer使用 \==进行判断可通过,但是区间之外的所有数据,则会在堆上新产生,不会通过。因此如果用\== 来比较数值,很可能在小的测试数据中通过,而到了生产环境才出问题。
-
+
**3.2【强制】 BigDecimal需要使用compareTo()**
因为BigDecimal的equals()还会比对精度,2.0与2.00不一致。
* Facebook-Contrib: Correctness - Method calls BigDecimal.equals()
-
+
**3.3【强制】 Atomic* 系列,不能使用equals方法**
因为 Atomic* 系列没有覆写equals方法。
@@ -86,7 +86,7 @@ if (counter1.get() == counter2.get()){...}
* [Sonar-2204: ".equals()" should not be used to test the values of "Atomic" classes](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-2204)
-
+
**3.4【强制】 double及float的比较,要特殊处理**
因为精度问题,浮点数间的equals非常不可靠,在vjkit的NumberUtil中有对应的封装函数。
@@ -134,7 +134,7 @@ long l = Integer.MAX_VALUE * 2L; //结果是正确的4294967294
* [Sonar-2184: Math operands should be cast before assignment](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-2184)
-
+
**4.2【强制】数字取模的结果不一定是正数,负数取模的结果仍然负数**
取模做数组下标时,如果不处理负数的情况,很容易ArrayIndexOutOfBoundException。
@@ -148,7 +148,7 @@ Math.abs(Integer.MIN_VALUE) = -2147483648;
* Findbugs: Style - Remainder of hashCode could be negative
-
+
**4.3【推荐】 double 或 float 计算时有不可避免的精度问题**
```java
@@ -216,7 +216,7 @@ for (int i = 0; i < 100; i++) {
* [Sonar-1643: Strings should not be concatenated using '+' in a loop](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-1643)
-
+
**6.2 【强制】 字符串拼接对象时,不要显式调用对象的toString()**
如上,`+`实际是StringBuilder,本身会调用对象的toString(),且能很好的处理null的情况。
@@ -229,17 +229,17 @@ str = "result:" + myObject.toString(); // myObject为Null时,抛NPE
str = "result:" + myObject; // myObject为Null时,输出 result:null
```
-
+
**6.3【强制】使用StringBuilder,而不是有所有方法都有同步修饰符的StringBuffer**
因为内联不成功,逃逸分析并不能抹除StringBuffer上的同步修饰符
* [Sonar-1149: Synchronized classes Vector, Hashtable, Stack and StringBuffer should not be used](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-1149)
-
+
**6.4 【推荐】当拼接后字符串的长度远大于16时,指定StringBuilder的大概长度,避免容量不足时的成倍扩展**
-
+
**6.5 【推荐】如果字符串长度很大且频繁拼接,可考虑ThreadLocal重用StringBuilder对象**
参考BigDecimal的toString()实现,及vjkit中的StringBuilderHolder。
diff --git a/standard/docs/chapter08.md b/standard/docs/chapter08.md
index 484c5523..ee9f032a 100644
--- a/standard/docs/chapter08.md
+++ b/standard/docs/chapter08.md
@@ -6,10 +6,10 @@
数组有大小限制,当超过容量时,需要进行复制式扩容,新申请一个是原来容量150% or 200%的数组,将原来的内容复制过去,同时浪费了内存与性能。HashMap/HashSet的扩容,还需要所有键值对重新落位,消耗更大。
-
+
默认构造函数使用默认的数组大小,比如ArrayList默认大小为10,HashMap为16。因此建议使用ArrayList(int initialCapacity)等构造函数,明确初始化大小。
-
+
HashMap/HashSet的初始值还要考虑加载因子:
为了降低哈希冲突的概率(Key的哈希值按数组大小取模后,如果落在同一个数组下标上,将组成一条需要遍历的Entry链),默认当HashMap中的键值对达到数组大小的75%时,即会触发扩容。因此,如果预估容量是100,即需要设定`100/0.75=134`的数组大小。vjkit的MapUtil的Map创建函数封装了该计算。
@@ -107,10 +107,10 @@ keySet遍历的方式,增加了N次用key获取value的查询。
推荐使用`java.util.concurrent(JUC)`工具包中的并发版集合,如ConcurrentHashMap等,优于使用Collections.synchronizedXXX()系列函数进行同步化封装(等价于在每个方法都加上synchronized关键字)。
-
+
例外:ArrayList所对应的CopyOnWriteArrayList,每次更新时都会复制整个数组,只适合于读多写很少的场景。如果频繁写入,可能退化为使用Collections.synchronizedList(list)。
-
+
2) 即使线程安全类仍然要注意函数的正确使用。
例如:即使用了ConcurrentHashMap,但直接是用get/put方法,仍然可能会多线程间互相覆盖。
@@ -156,7 +156,7 @@ Iterable integers = ...;
stack.pushAll(integers);
```
-
+
2) 如果集合要被写入,定义成` super T>`
```java
diff --git a/standard/docs/chapter09.md b/standard/docs/chapter09.md
index cd687059..8b659d32 100644
--- a/standard/docs/chapter09.md
+++ b/standard/docs/chapter09.md
@@ -44,12 +44,12 @@ Executors返回的线程池对象的弊端 :
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
-
+
2)CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
-
+
应通过 new ThreadPoolExecutor(xxx,xxx,xxx,xxx)这样的方式,更加明确线程池的运行规则,合理设置Queue及线程池的core size和max size,建议使用vjkit封装的ThreadPoolBuilder。
----
@@ -95,7 +95,7 @@ public void run() {
}
```
-
+
**5.1 正确处理InterruptException**
因为InterruptException异常是个必须处理的Checked Exception,所以run()所调用的子函数很容易吃掉异常并简单的处理成打印日志,但这等于停止了中断的传递,外层函数将收不到中断请求,继续原有循环或进入下一个堵塞。
@@ -115,7 +115,7 @@ public void myMethod() {
* [Sonar-2142: "InterruptedException" should not be ignored](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-2142)
-
+
**5.2 主循环及进入阻塞状态前要判断线程状态**
@@ -146,7 +146,7 @@ public void run() {
3) 如果没有在ThreadFactory设置自定义的UncaughtExceptionHanlder,则异常最终只打印在System.err,而不会打印在项目的日志中。
-
+
因此建议自写的Runnable都要保证捕获异常; 如果是第三方的Runnable,可以将其再包裹一层vjkit中的SafeRunnable。
```java
@@ -233,7 +233,7 @@ synchronized(A.class) {
2) Array Base的queue一般是全局一把锁,而Linked Base的queue一般是队头队尾两把锁。
-
+
* 分散锁(又称分段锁):
@@ -241,7 +241,7 @@ synchronized(A.class) {
2)对于经常写,少量读的计数器,推荐使用JDK8或vjkit封装的LongAdder对象性能更好(内部分散成多个counter,减少乐观锁的使用,取值时再相加所有counter)
-
+
* 无锁的数据结构:
diff --git a/standard/docs/chapter10.md b/standard/docs/chapter10.md
index 217200ea..073fab53 100644
--- a/standard/docs/chapter10.md
+++ b/standard/docs/chapter10.md
@@ -45,7 +45,7 @@ MyClass.class, "mymethod");
throw TIMEOUT_EXCEPTION;
```
-
+
2) 如果异常的message会变化,则对静态的异常实例进行clone()再修改message。
Exception默认不是Cloneable的,`CloneableException`见vjkit。
@@ -59,7 +59,7 @@ private static CloneableException TIMEOUT_EXCEPTION = new CloneableException("Ti
throw TIMEOUT_EXCEPTION.clone("Timeout for 40ms");
```
-
+
3)自定义异常,也可以考虑重载fillStackTrace()为空函数,但相对没那么灵活,比如无法按场景指定一层的StackTrace。
----
@@ -100,7 +100,7 @@ logger.error("user[" + userId + "] expired:" + e.getMessage(), e);
尽量使用JDK标准的Runtime异常如`IllegalArgumentException`,`IllegalStateException`,`UnsupportedOperationException`,项目定义的Exception如`ServiceException`。
-
+
**5.2 【推荐】根据调用者的需要来定义异常类,直接使用`RuntimeException`是允许的**
是否定义独立的异常类,关键是调用者会如何处理这个异常,如果没有需要特别的处理,直接抛出RuntimeException也是允许的。
@@ -115,7 +115,7 @@ logger.error("user[" + userId + "] expired:" + e.getMessage(), e);
捕获Throwable是为了捕获Error类异常,包括其实无法处理的`OOM` `StackOverflow` `ThreadDeath`,以及类加载,反射时可能抛出的`NoSuchMethodError` `NoClassDefFoundError`等。
-
+
**6.2【推荐】多个异常的处理逻辑一致时,使用JDK7的语法避免重复代码**
```java
@@ -149,7 +149,7 @@ try {
}
```
-
+
**7.2 【强制】异常处理不能吞掉原异常,要么在日志打印,要么在重新抛出的异常里包含原异常**
```java
@@ -166,7 +166,7 @@ throw new MyException("message", ex);
* [Sonar-1166: Exception handlers should preserve the original exceptions](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-1166),其中默认包含了InterruptedException, NumberFormatException,NoSuchMethodException等若干例外
-
+
**7.3 【强制】如果不想处理异常,可以不进行捕获。但最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容**
----
@@ -185,7 +185,7 @@ try (Writer writer = ...) {
}
```
-
+
**8.2 【强制】如果处理过程中有抛出异常的可能,也要做try-catch,否则finally块中抛出的异常,将代替try块中抛出的异常**
```java
@@ -208,7 +208,7 @@ try {
* [Sonar-1163: Exceptions should not be thrown in finally blocks](https://www.sonarsource.com/products/codeanalyzers/sonarjava/rules.html#RSPEC-1163)
-
+
**8.3 【强制】不能在finally块中使用return,finally块中的return将代替try块中的return及throw Exception**
```java
@@ -233,4 +233,4 @@ try {
----
* [上一章:并发处理](chapter09.md)
-* [下一章:日志规约](chapter11.md)
\ No newline at end of file
+* [下一章:日志规约](chapter11.md)
diff --git a/standard/docs/chapter11.md b/standard/docs/chapter11.md
index 2fde4849..654f4f98 100644
--- a/standard/docs/chapter11.md
+++ b/standard/docs/chapter11.md
@@ -27,7 +27,7 @@ logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);
```
-
+
但如果symbol.getMessage()本身是个消耗较大的动作,占位符在此时并没有帮助,须要改为条件判断方式来完全避免它的执行。
```java
diff --git a/standard/docs/chapter12.md b/standard/docs/chapter12.md
index b9f48f87..14495b63 100644
--- a/standard/docs/chapter12.md
+++ b/standard/docs/chapter12.md
@@ -17,10 +17,10 @@
1)获取当前毫秒数System.currentTimeMillis() 而不是new Date().getTime(),后者的消耗要大得多。
-
+
2)如果要获得更精确的,且不受NTP时间调整影响的流逝时间,使用System.nanoTime()获得机器从启动到现在流逝的纳秒数。
-
+
3)如果希望在测试用例中控制当前时间的值,则使用vjkit的Clock类封装,在测试和生产环境中使用不同的实现。
----
@@ -91,4 +91,4 @@ ReflectionUtils.invoke(obj, methodName, args);
----
-* [上一章:日志规约](chapter11.md)
\ No newline at end of file
+* [上一章:日志规约](chapter11.md)
diff --git a/standard/docs/merge.sh b/standard/docs/merge.sh
index 80019a6f..6057ea09 100755
--- a/standard/docs/merge.sh
+++ b/standard/docs/merge.sh
@@ -28,8 +28,5 @@ cat chapter12.md >> vip-java-standard.md
echo '\n' >> vip-java-standard.md
cat ali.md >> vip-java-standard.md
-sed -e "s|
||g" -i bak vip-java-standard.md
-sed -e "s|
||g" -i bak vip-java-standard.md
-
echo 'upload vip-java-standard.md to http://www.mdtr2pdf.com'
diff --git a/standard/formatter/README.md b/standard/formatter/README.md
index 814c1ac4..d1ffae4f 100644
--- a/standard/formatter/README.md
+++ b/standard/formatter/README.md
@@ -4,8 +4,8 @@
将下列profile下载并导入IDE即可,导入后Profile名称为`vipshop2.0`:
-* [Eclipse Code Formatter Profile](http://gitlab.tools.vipshop.com/venus-framework/vjtools/raw/master/standard/formatter/vipshop-code-conventions.xml)
-* [Intellij Code Formatter Profile](http://gitlab.tools.vipshop.com/venus-framework/vjtools/raw/master/standard/formatter/vipshop-code-conventions-idea.xml)
+* [Eclipse Code Formatter Profile](https://raw.githubusercontent.com/vipshop/vjtools/master/standard/formatter/vipshop-code-conventions.xml)
+* [Intellij Code Formatter Profile](https://raw.githubusercontent.com/vipshop/vjtools/master/standard/formatter/vipshop-code-conventions-idea.xml)
因为Intellij导入Eclipse Profile存在问题,因此同时提供了两者的Profile。
@@ -27,7 +27,6 @@
## 3. 与IDEA默认模板的区别
-详见 [idea和eclipse默认模板的区别](http://wiki.corp.vipshop.com/pages/viewpage.action?pageId=424282717)
本模板参考了Intellij IDEA默认模板中如下部分:
diff --git a/vjmap/README.md b/vjmap/README.md
index 95e5f9d1..8df09b20 100644
--- a/vjmap/README.md
+++ b/vjmap/README.md
@@ -8,7 +8,7 @@ vjmap 原始思路来源于[tbjmap](https://github.com/alibaba/TBJMap) 进行了
# 2.vjmap使用
-[下载](http://mvn1.tools.vipshop.com/nexus/index.html#nexus-search;quick~vjmap), 点击zip文件的`Artifact Information` Tab,下载并解压。
+maven编译后得到zip包,解压后运行。
注意:vjmap在执行过程中,会完全停止应用,必须摘流量执行!!!
diff --git a/vjtop/README.md b/vjtop/README.md
index 7a9a2ee5..e95a22ae 100644
--- a/vjtop/README.md
+++ b/vjtop/README.md
@@ -12,7 +12,7 @@
## 2.1 概述
-[下载包](http://mvn1.tools.vipshop.com/nexus/index.html#nexus-search;quick~vjtop), 点击zip文件的`Artifact Information` Tab,下载并解压。
+maven编译后得到zip包,解压后运行。
需要设置JAVA_HOME 环境变量,需要与所探测的JVM同一个用户,或Root用户运行