1. Mock Bean对象生成工具:random-beans
2. Bean属性复制:MapStruct
3. Java代码检查工具:Checker Framework
4. java相关的工具库:vjtools(唯品会出品)地址: https://github.com/benas/random-beans
随机生成Pojo对象,填充字段,UnitTest利器,牛逼之处在于
1) 能处理所有常见类型,包括枚举。
2) 能处理级联对象结构,Bean里嵌套Bean这种。
简单示例如下,90%的情况下都够用,再也不用new一个Bean,然后一顿Set属性了:
Person person =EnhancedRandom.random(Person.class); // one pojo
Stream<Person> persons = EnhancedRandom.randomStreamOf(10, Person.class); // batch 10 pojos
使用EnhancedRandom实现自定义规则的bean填充:
EnhancedRandom enhancedRandom = EnhancedRandomBuilder.aNewEnhancedRandom();
Person person = enhancedRandom.nextObject(Person.class);
EnhancedRandom random = EnhancedRandomBuilder.aNewEnhancedRandomBuilder()
.seed(123L)
.objectPoolSize(100)
.randomizationDepth(3)
.charset(forName("UTF-8"))
.timeRange(nine, five)
.dateRange(today, tomorrow)
.stringLengthRange(5, 50)
.collectionSizeRange(1, 10)
.scanClasspathForConcreteTypes(true)
.overrideDefaultInitialization(false)
.build();
更高级的定制,精确控制字段:
EnhancedRandom enhancedRandom = EnhancedRandomBuilder.aNewEnhancedRandomBuilder()
.randomize(String.class, (Randomizer<String>) () -> "foo")
.exclude(field().named("age").ofType(Integer.class).inClass(Person.class).get())
.build();
Person person = enhancedRandom.nextObject(Person.class);
地址: http://mapstruct.org/
牛逼之处在于可以处理不同名称的属性映射,也可以处理级联关系。
参考: https://blog.csdn.net/lx_yoyo/article/details/75061614
...
<properties>
<!-- <org.mapstruct.version>1.1.0.Beta1</org.mapstruct.version>-->
<org.mapstruct.version>1.1.0.Final</org.mapstruct.version>
</properties>
...
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<!-- <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>-->
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins></build>
...
其核心原理是通过@Mapper接口和@Mapping映射关系定义,自动生成一个MapperImpl实现类,在这个实现类里做生成好了setter属性值的代码。
@Mapper注解标记这个接口作为一个映射接口,并且是编译时MapStruct处理器的入口。
@Mapping解决源对象和目标对象中,属性名字不同的情况。
Mappers.getMapper自动生成的接口的实现可以通过Mapper的class对象获取,从而让客户端可以访问Mapper接口的实现。
@Mapper
public interface PeopleMapper {
PeopleMapper INSTANCE = Mappers.getMapper(PeopleMapper.class);
/**
* PO转DTO
*
* @param entity PO
* @return DTO
*/
@Mapping(target = "phoneNumber", source = "callNumber")
@Mapping(target = "user.name", source = "name")
@Mapping(target = "user.age", source = "age")
PeopleDTO entityToDTO(PeopleEntity entity);
/**
* DTO转PO
*
* @param peopleDTO DTO
* @param entity PO
*/
@Mapping(target = "callNumber", source = "phoneNumber")
@Mapping(target = "name", source = "user.name")
@Mapping(target = "age", source = "user.age")
void updateEntityFromDto(PeopleDTO peopleDTO, @MappingTarget PeopleEntity entity);
}
地址: https://checkerframework.org/
源码: https://github.com/typetools/checker-framework/
内置了几十种检查规则,也可以方便的自定义检查规则。
例如空指针检查:
public class NullnessExample {
public static void main(String[] args) {
Object myObject = null;
System.out.println(myObject.toString());
}
}
执行:
$ javacheck -processor org.checkerframework.checker.nullness.NullnessChecker NullnessExample.java
我们将看到:
NullnessExample.java:9: error: [dereference.of.nullable] dereference of possibly-null reference myObject
System.out.println(myObject.toString());
^
1 error
Java开发相关
Java开发相关
// 按时间区间内,线程占用的CPU排序,默认显示前10的线程,默认每10秒打印一次
./vjtop.sh <PID>
// 按线程从启动以来的总占用CPU来排序
./vjtop.sh --totalcpu <PID>
// 按时间区间内,线程占用的SYS CPU排序
./vjtop.sh --syscpu <PID>
// 按线程从启动以来的总SYS CPU排序
./vjtop.sh --totalsyscpu <PID>
输出示例:
PID: 191082 - 17:43:12 JVM: 1.7.0_79 USER: calvin UPTIME: 2d02h
PROCESS: 685.00% cpu(28.54% of 24 core), 787 thread
MEMORY: 6626m rss, 6711m peak, 0m swap | DISK: 0B read, 13mB write
THREAD: 756 live, 749 daemon, 1212 peak, 0 new | CLASS: 15176 loaded, 161 unloaded, 0 new
HEAP: 630m/1638m eden, 5m/204m sur, 339m/2048m old
NON-HEAP: 80m/256m/512m perm, 13m/13m/240m codeCache
OFF-HEAP: 0m/0m direct(max=2048m), 0m/0m map(count=0), 756m threadStack
GC: 6/66ms/11ms ygc, 0/0ms fgc | SAFE-POINT: 6 count, 66ms time, 5ms syncTime
TID NAME STATE CPU SYSCPU TOTAL TOLSYS
23 AsyncAppender-Worker-ACCESSFILE-ASYNC WAITING 23.56% 6.68% 2.73% 0.72%
560 OSP-Server-Worker-4-5 RUNNABLE 22.58% 10.67% 1.08% 0.48%
9218 OSP-Server-Worker-4-14 RUNNABLE 22.37% 11.45% 0.84% 0.40%
8290 OSP-Server-Worker-4-10 RUNNABLE 22.36% 11.24% 0.88% 0.41%
8425 OSP-Server-Worker-4-12 RUNNABLE 22.24% 10.72% 0.98% 0.47%
8132 OSP-Server-Worker-4-9 RUNNABLE 22.00% 10.68% 0.90% 0.42%
8291 OSP-Server-Worker-4-11 RUNNABLE 21.80% 10.09% 0.89% 0.41%
8131 OSP-Server-Worker-4-8 RUNNABLE 21.68% 9.77% 0.93% 0.44%
9219 OSP-Server-Worker-4-15 RUNNABLE 21.56% 10.43% 0.90% 0.41%
8426 OSP-Server-Worker-4-13 RUNNABLE 21.35% 10.42% 0.66% 0.31%
Total : 668.56% cpu(user=473.25%, sys=195.31%) by 526 atcive threads(which cpu>0.05%)
Setting: top 10 threads order by CPU, flush every 10s
Input command (h for help):
进程区数据解释:
PROCESS: thread: 进程的操作系统线程数, cxtsw为主动与被动的线程上下文切换数
MEMORY: rss 为 Resident Set Size, 进程实际占用的物理内存; peak为最峰值的rss; swap为进程被交换到磁盘的虚拟内存。
DISK: 真正达到物理存储层的读/写的速度。
THREAD: Java线程数, active为当前线程数, daemon为active线程中的daemon线程数, new为刷新周期内新创建的线程数。
CLASS: loaded为当前加载的类数量,unloaded为总卸载掉的类数量,new为刷新周期内新加载的类数量。
HEAP: 1.0.3版开始每一项有三个数字, 分别为1.当前使用内存, 2.当前已申请内存, 3.最大内存; 如果后两个数字相同时则合并。
sur: 当前存活区的大小,注意实际有from, to 两个存活区。
NON-HEAP: 数字含义同HEAP
codeCache: JIT编译的二进制代码的存放区,满后将不能编译新的代码。
direct: 堆外内存,三个数字含义同HEAP, 未显式设置最大内存时,约等于堆内存大小。注意新版Netty不经过JDK API所分配的堆外内存未在此统计。
map: 映射文件内存,三个数字分别为1. map数量,2.当前使用内存,3.当前已申请内存,没有最大值数据。
threadStack: Java线程所占的栈内存总和,但不包含VM线程。(since 1.0.3)
ygc: YoungGC, 三个数字分别为次数/总停顿时间/平均停顿时间
fgc: OldGC + FullGC, 两个数字分别为次数/总执行时间,注意此时间仅为执行时间,非JVM停顿时间。
SAFE-POINT: PerfData开启时可用,JVM真正的停顿次数及停顿时间,以及等待所有线程进入安全点所消耗的时间。
线程区数据解释:
CPU: 线程在打印间隔内使用的CPU百分比(按单个核计算)
SYSCPU: 线程在打印间隔内使用的SYS CPU百分比(按单个核计算)
TOTAL: 从进程启动到现在,线程的总CPU时间/进程的总CPU时间的百分比
TOLSYS: 从进程启动到现在,线程的总SYS CPU时间/进程的总CPU时间的百分比
底部数据解释:
如果该线程的平均使用CPU少于单核的0.1%,这条线程将不参与排序显示,减少消耗。
JVM优化参数
JVM参数的精髓都在这里,而且是以实例脚本的形式实现的,直接可以拿来用:
https://github.com/vipshop/vjtools/blob/master/vjstar/src/main/script/jvm-options/jvm-options.sh
脚本片段如下:
# 启动时预申请内存
MEM_OPTS="$MEM_OPTS -XX:+AlwaysPreTouch"
# 如果线程数较多,函数的递归较少,线程栈内存可以调小节约内存,默认1M。
#MEM_OPTS="$MEM_OPTS -Xss256k"
# 堆外内存的最大值默认约等于堆大小,可以显式将其设小,获得一个比较清晰的内存总量预估
#MEM_OPTS="$MEM_OPTS -XX:MaxDirectMemorySize=2g"
# 根据JMX/VJTop的观察,调整二进制代码区大小避免满了之后不能再JIT,JDK7/8,是否打开多层编译的默认值都不一样
#MEM_OPTS="$MEM_OPTS -XX:ReservedCodeCacheSize=240M"
## GC Options##
GC_OPTS="-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly"
# System.gc() 使用CMS算法
GC_OPTS="$GC_OPTS -XX:+ExplicitGCInvokesConcurrent"
# CMS中的下列阶段并发执行
GC_OPTS="$GC_OPTS -XX:+ParallelRefProcEnabled -XX:+CMSParallelInitialMarkEnabled"
# 根据应用的对象生命周期设定,减少事实上的老生代对象在新生代停留时间,加快YGC速度
GC_OPTS="$GC_OPTS -XX:MaxTenuringThreshold=3"
# 如果OldGen较大,加大YGC时扫描OldGen关联的卡片,加快YGC速度,默认值256较低
GC_OPTS="$GC_OPTS -XX:+UnlockDiagnosticVMOptions -XX:ParGCCardsPerStrideChunk=1024"
# 如果JVM并不独占机器,机器上有其他较繁忙的进程在运行,将GC线程数设置得比默认值(CPU核数*5/8 )更低以减少竞争,反而会大大加快YGC速度。
# 另建议CMS GC线程数简单改为YGC线程数一半.
#GC_OPTS="$GC_OPTS -XX:ParallelGCThreads=12 -XX:ConcGCThreads=6"
# 如果CMS GC时间很长,并且明显受新生代存活对象数量影响时打开,但会导致每次CMS GC与一次YGC连在一起执行,加大了事实上JVM停顿的时间。
#GC_OPTS="$GC_OPTS -XX:+CMSScavengeBeforeRemark"
# 如果永久代使用不会增长,关闭CMS时ClassUnloading,降低CMS GC时出现缓慢的几率
#if [[ "$JAVA_VERSION" > "1.8" ]]; then
# GC_OPTS="$GC_OPTS -XX:-CMSClassUnloadingEnabled"
#fi