转载

小工具推荐(random-beans/MapStruct/Checker Framework/vjtools)

1. Mock Bean对象生成工具:random-beans

2. Bean属性复制:MapStruct

3. Java代码检查工具:Checker Framework

4. java相关的工具库:vjtools(唯品会出品)

小工具推荐

  1. Mock Bean对象生成工具:random-beans
  2. Bean属性复制:MapStruct
  3. Java代码检查工具:Checker Framework
  4. java相关的工具库:vjtools(唯品会出品)

1. Mock Bean对象生成工具:random-beans

地址: 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);

2. Bean属性复制:MapStruct

地址: 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);
}

3. Java代码检查工具:Checker Framework

地址: 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

4. java相关的工具库:vjtools(唯品会出品)

Java开发相关

  • standard Java开发手册
  • code formatter IDE格式化模板
  • sonar rule Sonar规则定制示例
  • vjkit 关于文本,集合,并发等基础功能的核心类库
  • vjstar 关于后端应用的性能、可用性的最佳实践

Java开发相关

  • vjtop 观察JVM进程指标及其繁忙线程
  • vjmap JMAP的分代打印版
  • vjdump 线上紧急收集JVM数据脚本
  • vjmxcli JMX 查看工具
    以vjtop为例:找出CPU最繁忙的线程
// 按时间区间内,线程占用的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
原文  https://blog.csdn.net/KimmKing/article/details/82391835
正文到此结束
Loading...