How to get the OpenJDK binary tar/zip file?

Since Oracle updated their license for Java 8, a lot of companies started officially maintaining OpenJDK, such as Redhat, Amazon, Alibaba and etc. It’s a good time to switch to OpenJDK.

Unlike Oracle, Redhat doesn’t provide the portable tar/zip of pre-built OpenJDK Linux edition. The zip files are only for Windows. Redhat recommends you to use the offical RPM package to install. Generally, it’s better solution but sometimes it’s very inconvenience, especially when you don’t have the permission but you want to have a quick deployment.

What to do? Docker could help!

  • Pull the image of the CentOS you need. In my case, I used a CentOS 7.7 image.

  • Start the container

  • Install the OpenJDK you need, such as OpenJDK8 or OpenJDK11. For example,

  • Find where the JDK is. In my case, it’s /usr/lib/jvm/java-11-openjdk-11.0.5.10-0.el7_7.x86_64

  • Make a tar file of that folder
  • Copy this tar file out to your local.

By this way, you can get the compatible tar/zip file out. Usually, the dependencies should be fulfilled.

Build OpenJFX 8 in CentOS 6.7 Docker Container

OpenJDK 8 doesn’t include OpenJFX by default. And to make OpenJFX work on old Linux distribution, such as CentOS 6.7, you can not simply follow the official instructions. This article will talk about how to build OpenJFX 8 in CentOS 6.7 docker container.

Start docker container

With docker, it’s extremely easy to get CentOS 6.7 environment.

Instructions

Yum Install Packages


Install GCC/G++ 6, Python 2.7, Ruby 2.4

Reference is https://www.softwarecollections.org/en/scls/rhscl/devtoolset-6/.


Install Gradle, CMake, Ant

Install gradle 4.8 and ant 1.10, update $PATH.


Sync OpenJFX 8 source code

Build without Webkit

Skip the samples and scene-builder build – “vim rt/build.gradle” and comment on the following lines

Start Gradle build.


when the build is done, the javafxsdk-overlay.zip will be generated.


Build with Webkit

With WebKit, the compilation will become extremely slow.

Before doing the steps of “Build without Webkit”, do the following extra steps.

Copy the gradle.properties from the template and enable the Webkit compiling

Enable “COMPILE_WEBKIT“, “BUILD_JAVADOC“, “BUILD_SRC_ZIP“, And specify COMPILE_TARGETS as “linux”

Update buildSrc/linux.gradle a little bit.


Update the symbolic link of /usr/bin/python2

Do the steps of “Build without Webkit“.

 

写个Hadoop Map-Reduce分析NCDC的天气数据

我是Hadoop小白,写本文是总结笔记,怕之后忘了。

搭个Hadoop Cluster

因为手头有几个Raspberry Pi 3的板子,就花了点时间搭了一个小的Hadoop Cluster的集群,四个Slave with Raspbian, Master server在一个虚拟机里安装了Ubuntu 18.04。关于如何配置,IBM上的这篇Blog讲得非常详细。

NCDC的天气数据

在《Hadoop Definitive Guide》上讲到使用NCDC(National Climatic Data Center)的天气数据来分析每年最高的气温。这本书在Github上有1901年和1902年的数据,但如果你想试试更大的数据集就需要自己下载了。

这里有一个Shell Script可以帮你从NCDC的FTP上下载天气数据。你只需要给出起始和终止年份。

下载之后,天气数据会分到不同的zip文件里,但如果上传到HDFS上还要把它放到一个文件里。下面这段Python代码就做这个事情。

要注意的就是,这段代码要运行在天气的Zip同一个文件夹里。

我下载了1901年到1935年的数据,大约400多M,使用hadoop fs的命令上传到HDFS上,

然后就可以写一个简单的Map – Reduce了。

因为HDFS一个Block是128M,所以400M需要4个Block。

Map-Reduce

首先是Mapper,其实就是分析天气文件的每一行,从里面取出温度。

Reducer则是从前面得到的年份和温度的信息汇总在一些,求出当年里最高的气温。

这个过程很像Java 8里引入的Stream。

之后,还要实现一个Job来执行这个Map-Reduce任务。

这个程序需要两个路径,一是NCDC的数据文件,一是结果的输出路径。Job还要需要明确Mapper和Recuder的类名。

生成Jar文件后,使用下面的命令行运行Map-Reduce任务

结果会被发到output4文件夹里,几分钟后,就可以看到结果了。

好了,Hadoop里的HelloWorld算是完成了!

References

 

[VS Code Tips] How to Make AssertJ Be Static Imported in VS Code

After installing the famous Java plugin written by RedHat, VS Code will become into a powerful Java IDE, which is far beyond other editors, such as Sublime, Notepad++.

Today’s tip will show you how to static import AssertJ in VS Code. AssertJ helps you to write assertions in unit testing. Compared to Hamcrest, someone, like me, think AssertJ’s API and syntax make more sense.

First, you need to introduce it. In maven, it’s very straightforward. Simply define a new dependency in pom.xml.

Next step is to update a configuration “java.completion.favoriteStaticMembers“. Otherwise, assertThat() will be the one in Hamcrest in the auto-completion. Remove “org.junit.Assert.*” from the user configuration and add “org.assertj.core.api.Assertions.*” instead.

Now, AssertJ will be statically imported into your unit testing.

Mixin by Interface Default Method in Java 8

In Java 8, the feature of interface Default Method was introduced.

Java 8 introduces “Default Method” or (Defender methods) new feature, which allows developer to add new methods to the interfaces without breaking the existing implementation of these interfaces. It provides flexibility to allow interface define implementation which will use as default in the situation where a concrete class fails to provide an implementation for that method.

This is a very interesting feature and also very useful. With it, we can implement kind of Mixin. Let’s see following case.

Before Java 8

In a system, there is real dog and robot dog, both of them can bark. Before Java 8, we may have the following interface and classes.

Maybe you already see the problem. Dog and RobotDog have the same implementation of method bark(). It’s duplication. It’s not easy to fix this problem, since Dog and RobotDog have different parent classes. RobotDog is not a Dog but it can bark. In Java, there is no multiple inheritance.

With Default Method in Java 8

With default method, the implementation can be more elegant. See the following code.

As you can see, the same logic can easily be extracted into another interface and the implementation of Dog and RobotDog looks simpler.

How about making a RobotDog flying? It’s simple and there can have different options of flying.

Now I have a RobotDog, which can bark as a dog and fly as a bird!

ND4j的CPU与GPU简单性能对比

最近在学习Deep Learning。ND4j是一个类似于Python Numpy的Java版本实现,支持CPU和GPU Backend。很是好奇,这两者性能到底能差多少,于是做了一个小的测试。

安装CUDA Toolkit 8.0

最新的CUDA Tooklit版本是9.1,但是目前最新ND4j的Release版本(0.9.1)还不支持。(看了ND4j论坛里的讨论,master branch已经支持9.1)0.9.1只支持CUDA 7.5和8.0,我的实验中,安装了8.0版本。在这里下载Installer和Patch。

安装完成后,机器要重启一下。

ND4j的Maven配置

在Maven里通过切换Nd4j的artifactId来设置CPU或GPU Backend。

nd4j-native-platform是CPU Backend,nd4j-cuda-8.0-platform是GPU Backend。

一个简单的测试

下面是一个简单的测试代码,两个10K by 10K的Matrices做Outer Product。

我的CPU是i7-5820K,GPU是GTX 970 3.5GB。测试结果真的非常让人吃惊 – GPU 497ms, CPU 7827ms. 差了约16倍。

我终于知道NViDIA的股价为什么涨这么多了!😁

 

用SWTBot+Junit+Truth做GUI层面的Unit Testing

在开发组里,Unit Testing的方法已经深入人心,Case的数量也越来越多。可因为GUI层面代码的特殊性,目前大多数的测试都针对非GUI层面的Code。这使得占总代码量40%的GUI层面很少被单元测试覆盖。

本文通过一个简单的例子,结合SWTBot,Junit和Truth,实现了GUI层面的单元测试。

SWTBot的安装

SWTBot可以通过Update Site(http://download.eclipse.org/technology/swtbot/releases/latest/)安装。

在开发项目中也要加入SWTBot的依赖,

一个简单的Dialog

让我们来实现一个简单的对话框,用来做两个数的加法。

代码如下:

这里特别使用了setData方法对几个关键的控件设置了“id”,这是为了能在SWTBot中更方便准确的定位待测试的控件。

SWTBot+JUnit+Truth

待测的对话框已经准备好了,下面来写一个简单的单元测试。

几点要注意的地方,

  • 测试Dialog时,要使用setBlockOnOpen(false),否则open()方法会把后续测试代码阻塞掉。
  • SWTBot搜索控件的办法有几种,以Text控件为例,介绍几个常用的。
    • text()等价于text(0), 就是找第一个Text控件
    • text(n), 按顺序找第n个控件
    • textWithLabelInGroup(label, inGroup)等价于textWithLabelInGroup(label, inGroup,0),就是找在某个Group里的第0个Label为”label”的Text控件
    • textWithLabelInGroup(label, inGroup,n),就是找在某个Group里的第n个Label为”label”的Text控件
    • textInGroup(text, inGroup)等价于textInGroup(text, inGroup, 0), 找在某个Group里第0个text为“text”的Text控件
    • textInGroup(text, inGroup, n), 找在某个Group里第n个text为“text”的Text控件
    • textWithId(key, data), 找出key=data的Text控件。这就是和前面setData()相对应的一个API。用ID找还有一个更简单的API–textWithId(value),这个API没有输入key,原因是SWTBot有个Preference给DEFAULT_KEY–org.eclipse.swtbot.search.defaultKey,默认的值为
      “org.eclipse.swtbot.widget.key”
  • 对不同的控件,API会略有不同,不过大同小异。SWTBot现在除了支持基本的SWT控件外,还支持了Nebula Grid,NatTable,GEF等复杂的控件。
  • 写Assertion的部分和普通的Unit Test并没有什么不同。
  • 因为这种Unit Test的写法和普通的JUnit并没有什么不同,所以Headless Build就可以用一般maven test。当然,如果是开发RCP应用,一定要使用Eclipse Tycho插件。
  • 还有一点不同的事,SWTBot的Case一定要在X环境下。如果Build Server上并没有开X环境,需要要安装Xvfb

总结

通过一个小例子,本文讨论了如何使用SWTBot对小型的SWT开发单元,如对话框、Composite等,进行单元测试(SWTBot也可以测试完整的大型应用)。

现在可以慢慢完善GUI层面的单元测试了,下一步也许可以和Cucumber之类的Framework结合起来。😁

 

 

 

Java坑之Class.isEnum()

发现在这个坑是因为代码里用到了cloning库

在做深度代码拷贝时,发现Enum对象也被Copy了,破坏了Enum对象的唯一性。读了cloning的源代码,其实它考虑了Enum的问题,默认也是跳过的。在其1.9.0版本,它使用了Class.isEnum()来检查,但在1.9.2版本中,检查的代码换成了instanceof Enum, 问题也解决了。对比一下,两种API的区别,

输出是

第二行的输出居然是false, 再看看A2的类签名,不是A,而是一个匿名类A$1。这都是因为A2有Override toString方法,Java产生的了一个匿名类。再看看isEnum的实现,

这下都清楚了,JDK里使用通过基本类是否是Enum的方法,判断当前类是否是Enum, 但当有匿名类的出现,父类就不再是Enum,isEnum的检查也就失效了。

难道Enum的匿名类就不是Enum了吗?😈

这个坑大家要小心啊!