You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by gr...@apache.org on 2019/11/20 19:21:13 UTC

[kudu] branch master updated (80e2850 -> 74b9ac6)

This is an automated email from the ASF dual-hosted git repository.

granthenke pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git.


    from 80e2850  [clock] run TestNtpDiagnostics against chrony as well
     new 29b2b4d  [Java] Upgrade dependencies
     new 74b9ac6  [java] Fix medium SpotBugs issues

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 java/buildSrc/build.gradle                         |  15 +-
 .../org/apache/kudu/gradle/DistTestTask.java       |   9 +-
 java/config/checkstyle/checkstyle.xml              |   8 +-
 java/config/spotbugs/excludeFilter.xml             | 179 +++++++++++++++++++++
 java/gradle/dependencies.gradle                    |  27 ++--
 java/gradle/quality.gradle                         |   3 +
 java/gradle/wrapper/gradle-wrapper.properties      |   2 +-
 java/gradlew                                       |  35 ++--
 java/kudu-backup-tools/build.gradle                |   5 +
 .../apache/kudu/backup/TestKuduBackupLister.scala  |  24 +--
 .../org/apache/kudu/backup/KuduBackupRDD.scala     |   1 +
 .../org/apache/kudu/backup/TestKuduBackup.scala    |   8 +-
 .../tools/IntegrationTestBigLinkedList.java        |  18 ++-
 .../apache/kudu/mapreduce/tools/ITImportCsv.java   |  12 +-
 .../kudu/mapreduce/tools/ITImportParquet.java      |   6 -
 .../mapreduce/tools/ITImportParquetPreCheck.java   |   6 -
 .../main/java/org/apache/kudu/ColumnSchema.java    |   2 +-
 .../org/apache/kudu/client/AsyncKuduScanner.java   |   8 +-
 .../main/java/org/apache/kudu/client/Bytes.java    |   3 +-
 .../org/apache/kudu/client/KuduPartitioner.java    |  14 ++
 .../java/org/apache/kudu/client/KuduScanToken.java |  14 ++
 .../java/org/apache/kudu/client/RpcTraceFrame.java |   6 +-
 .../java/org/apache/kudu/client/ServerInfo.java    |   2 +-
 .../apache/kudu/client/ITScannerMultiTablet.java   |   2 +-
 .../apache/kudu/client/TestAsyncKuduSession.java   |   6 +-
 .../kudu/client/TestFlexiblePartitioning.java      |   6 +-
 .../org/apache/kudu/client/TestHybridTime.java     |   4 +-
 .../org/apache/kudu/client/TestKuduPredicate.java  |   2 +-
 .../java/org/apache/kudu/client/TestKuduTable.java |   2 +-
 .../org/apache/kudu/client/TestLeaderFailover.java |   2 +-
 .../org/apache/kudu/client/TestNegotiator.java     |   6 +-
 .../apache/kudu/client/TestPartitionPruner.java    |   2 +-
 .../java/org/apache/kudu/client/TestRowErrors.java |   2 +-
 .../java/org/apache/kudu/client/TestRowResult.java |   2 +-
 .../org/apache/kudu/client/TestScanPredicate.java  |  26 +--
 .../apache/kudu/client/TestScannerMultiTablet.java |   2 +-
 .../org/apache/kudu/client/TestStatistics.java     |   2 +-
 .../hive/metastore/TestKuduMetastorePlugin.java    |   2 +-
 java/kudu-jepsen/build.gradle                      |   6 +-
 .../java/org/apache/kudu/mapreduce/JarFinder.java  |   9 +-
 .../kudu/mapreduce/KuduTableMapReduceUtil.java     |  56 +++----
 .../kudu/mapreduce/HadoopTestingUtility.java       |   3 +-
 .../apache/kudu/mapreduce/ITInputFormatJob.java    |  10 +-
 .../apache/kudu/mapreduce/ITOutputFormatJob.java   |   6 +-
 .../org/apache/kudu/mapreduce/TestJarFinder.java   |  17 +-
 java/kudu-spark/build.gradle                       |   7 +-
 .../org/apache/kudu/spark/kudu/KuduContext.scala   |   6 +-
 .../scala/org/apache/kudu/spark/kudu/KuduRDD.scala |   1 +
 .../apache/kudu/spark/kudu/DefaultSourceTest.scala |   4 +-
 .../apache/kudu/spark/kudu/KuduContextTest.scala   |   5 +-
 .../org/apache/kudu/spark/kudu/KuduTestSuite.scala |   7 +-
 .../org/apache/kudu/spark/kudu/SparkSQLTest.scala  |  33 ++--
 .../org/apache/kudu/test/CapturingLogAppender.java |   4 +-
 .../kudu/test/CapturingToFileLogAppender.java      |   4 +-
 .../java/org/apache/kudu/test/ClientTestUtil.java  |   2 +-
 .../java/org/apache/kudu/test/KuduTestHarness.java |   4 +-
 .../kudu/test/cluster/KuduBinaryJarExtractor.java  |   3 +-
 .../apache/kudu/test/cluster/MiniKuduCluster.java  |  10 +-
 .../apache/kudu/test/junit/TestResultReporter.java |   5 +-
 59 files changed, 450 insertions(+), 227 deletions(-)
 create mode 100644 java/config/spotbugs/excludeFilter.xml


[kudu] 01/02: [Java] Upgrade dependencies

Posted by gr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

granthenke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git

View the commit online:
https://github.com/apache/kudu/commit/29b2b4d27a62eeb92d52e61cafdee6ac333de316

commit 29b2b4d27a62eeb92d52e61cafdee6ac333de316
Author: Grant Henke <gr...@apache.org>
AuthorDate: Tue Nov 19 15:05:01 2019 -0600

    [Java] Upgrade dependencies
    
    Upgrades the Java dependencies and Gradle versions.
    
    Major version upgrades:
    - mockito 2.27.0 -> 3.1.0
    
    Minor version upgrades:
    - guava 27.1-jre -> 28.1-jre
    - hamcrest 2.1 -> 2.2
    - protobuf 3.7.1 -> 3.10.0
    - yetus 0.10.0 -> 0.11.1
    
    Maintenance version upgrades:
    - hadoop 3.2.0 - 3.2.1
    - httpClient 4.5.8 -> 4.5.10
    - jetty 9.4.18.v20190429 -> 9.4.22.v20191022
    - scalatest 3.0.7 -> 3.0.8
    
    Gradle upgrades:
    - gradle 5.4.1 -> 5.6.4
    - gradle-errorprone-plugin 0.8 -> 1.1.1
    - gradle-version 0.21.0 -> 0.27.0
    - gson 2.8.5 -> 2.8.6
    - nebula-clojure-plugin 8.1.1 -> 9.1.1
    - protobuf-gradle-plugin 0.8.8 -> 0.8.10
    - shadow 5.0.0 -> 5.2.0
    - spotbugs-gradle-plugin 1.7.1 -> 2.0.1
    
    I also set checkstyle to 8.26 to ensure Gradle upgrades don’t change the
    version and break.
    
    Change-Id: Iee6b7b178f1dd7412ecb88261ef88f282c5744e7
    Reviewed-on: http://gerrit.cloudera.org:8080/14746
    Tested-by: Grant Henke <gr...@apache.org>
    Reviewed-by: Alexey Serbin <as...@cloudera.com>
---
 java/buildSrc/build.gradle                    | 15 ++++++------
 java/config/checkstyle/checkstyle.xml         |  8 +++---
 java/gradle/dependencies.gradle               | 27 +++++++++++----------
 java/gradle/quality.gradle                    |  1 +
 java/gradle/wrapper/gradle-wrapper.properties |  2 +-
 java/gradlew                                  | 35 ++++++++++++---------------
 6 files changed, 43 insertions(+), 45 deletions(-)

diff --git a/java/buildSrc/build.gradle b/java/buildSrc/build.gradle
index 7560ecd..55112ba 100644
--- a/java/buildSrc/build.gradle
+++ b/java/buildSrc/build.gradle
@@ -28,17 +28,18 @@ repositories {
 // Manage plugin dependencies since the plugin block can't be used in included build scripts yet.
 // For more details see: https://docs.gradle.org/current/userguide/plugins.html#plugins_dsl_limitations
 dependencies {
-  compile "com.github.ben-manes:gradle-versions-plugin:0.21.0"
-  compile "com.github.jengelman.gradle.plugins:shadow:5.0.0"
+  compile "com.github.ben-manes:gradle-versions-plugin:0.27.0"
+  compile "com.github.jengelman.gradle.plugins:shadow:5.2.0"
   compile "gradle.plugin.com.google.gradle:osdetector-gradle-plugin:1.6.2"
-  compile "com.google.protobuf:protobuf-gradle-plugin:0.8.8"
-  compile "com.netflix.nebula:nebula-clojure-plugin:8.1.1"
-  compile "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.7.1"
+  compile "com.google.protobuf:protobuf-gradle-plugin:0.8.10"
+  compile "com.netflix.nebula:nebula-clojure-plugin:9.1.1"
+  compile "com.github.spotbugs:spotbugs-gradle-plugin:2.0.1"
   compile "io.spring.gradle:propdeps-plugin:0.0.9.RELEASE"
-  compile "net.ltgt.gradle:gradle-errorprone-plugin:0.8"
+  compile "net.ltgt.gradle:gradle-errorprone-plugin:1.1.1"
   compile "ru.vyarus:gradle-animalsniffer-plugin:1.5.0"
-  compile "com.google.code.gson:gson:2.8.5"
+  compile "com.google.code.gson:gson:2.8.6"
   compile "cz.alenkacz:gradle-scalafmt:1.7.2"
+  compile "com.google.guava:guava:28.1-jre"
 }
 
 // Compiler configuration
diff --git a/java/config/checkstyle/checkstyle.xml b/java/config/checkstyle/checkstyle.xml
index 562955d..633ea40 100644
--- a/java/config/checkstyle/checkstyle.xml
+++ b/java/config/checkstyle/checkstyle.xml
@@ -59,6 +59,10 @@
         <property name="file" value="${config_loc}/suppressions.xml"/>
         <property name="optional" value="false"/>
     </module>
+    <module name="LineLength">
+        <property name="max" value="100"/>
+        <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
+    </module>
     <module name="TreeWalker">
         <module name="OuterTypeFilename"/>
         <module name="IllegalTokenText">
@@ -73,10 +77,6 @@
             <property name="allowByTailComment" value="true"/>
             <property name="allowNonPrintableEscapes" value="true"/>
         </module>
-        <module name="LineLength">
-            <property name="max" value="100"/>
-            <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
-        </module>
         <module name="AvoidStarImport"/>
         <module name="OneTopLevelClass"/>
         <module name="NoLineWrap"/>
diff --git a/java/gradle/dependencies.gradle b/java/gradle/dependencies.gradle
index 7471cec..3334c1a 100755
--- a/java/gradle/dependencies.gradle
+++ b/java/gradle/dependencies.gradle
@@ -27,37 +27,38 @@ ext {
 versions += [
     async          : "1.4.1",
     avro           : "1.8.2",
+    checkstyle     : "8.26",
     clojure        : "1.9.0",
     clojureToolsCli: "0.4.1",
     commonsIo      : "2.6",
     errorProne     : "2.3.3",
     errorProneJavac: "9+181-r4173-1",
-    gradle         : "5.4.1",
-    guava          : "27.1-jre",
-    hadoop         : "3.2.0",
-    hamcrest       : "2.1",
+    gradle         : "5.6.4",
+    guava          : "28.1-jre",
+    hadoop         : "3.2.1",
+    hamcrest       : "2.2",
     hdrhistogram   : "2.1.11",
     hive           : "2.3.4",
-    httpClient     : "4.5.8",
+    httpClient     : "4.5.10",
     jepsen         : "0.1.5",
-    jetty          : "9.4.18.v20190429",
+    jetty          : "9.4.22.v20191022",
     jsr305         : "3.0.2",
     junit          : "4.12",
     log4j          : "2.11.2",
-    mockito        : "2.27.0",
+    mockito        : "3.1.0",
     murmur         : "1.0.0",
     netty          : "3.10.6.Final",
     osdetector     : "1.6.2",
     parquet        : "1.10.1",
     pmd            : "5.8.1",
-    protobuf       : "3.7.1",
+    protobuf       : "3.10.0",
     scala          : "2.11.12",
-    scalatest      : "3.0.7",
+    scalatest      : "3.0.8",
     scopt          : "3.7.1",
-    slf4j          : "1.7.26",
-    spark          : "2.4.3",
-    spotBugs       : "3.1.6",
-    yetus          : "0.10.0"
+    slf4j          : "1.7.29",
+    spark          : "2.4.4",
+    spotBugs       : "3.1.12",
+    yetus          : "0.11.1"
 ]
 
 // Log the Gradle version used vs defined.
diff --git a/java/gradle/quality.gradle b/java/gradle/quality.gradle
index 8bdc21a..0b35cab 100644
--- a/java/gradle/quality.gradle
+++ b/java/gradle/quality.gradle
@@ -26,6 +26,7 @@ apply plugin: "scalafmt" // Automatically formats Scala code on each build.
 apply plugin: "net.ltgt.errorprone" // Performs static code analysis to look for bugs in Java code.
 
 checkstyle {
+  toolVersion = versions.checkstyle
   configDir = file("$rootProject.projectDir/config/checkstyle")
   ignoreFailures = true
   showViolations = true
diff --git a/java/gradle/wrapper/gradle-wrapper.properties b/java/gradle/wrapper/gradle-wrapper.properties
index ee69dd6..0ebb310 100644
--- a/java/gradle/wrapper/gradle-wrapper.properties
+++ b/java/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/java/gradlew b/java/gradlew
index c40d514..fa8f2d4 100755
--- a/java/gradlew
+++ b/java/gradlew
@@ -7,7 +7,7 @@
 # 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
+#      https://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,
@@ -138,8 +138,8 @@ if $darwin; then
     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
 fi
 
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
     JAVACMD=`cygpath --unix "$JAVACMD"`
@@ -167,19 +167,19 @@ if $cygwin ; then
         else
             eval `echo args$i`="\"$arg\""
         fi
-        i=$((i+1))
+        i=`expr $i + 1`
     done
     case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+        0) set -- ;;
+        1) set -- "$args0" ;;
+        2) set -- "$args0" "$args1" ;;
+        3) set -- "$args0" "$args1" "$args2" ;;
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
     esac
 fi
 
@@ -188,14 +188,9 @@ save () {
     for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
     echo " "
 }
-APP_ARGS=$(save "$@")
+APP_ARGS=`save "$@"`
 
 # Collect all arguments for the java command, following the shell quoting and substitution rules
 eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
 
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
 exec "$JAVACMD" "$@"


[kudu] 02/02: [java] Fix medium SpotBugs issues

Posted by gr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

granthenke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git

View the commit online:
https://github.com/apache/kudu/commit/74b9ac67a1d3378e0fc38bd2ce827bacafde4775

commit 74b9ac67a1d3378e0fc38bd2ce827bacafde4775
Author: Grant Henke <gr...@apache.org>
AuthorDate: Tue Nov 19 15:20:52 2019 -0600

    [java] Fix medium SpotBugs issues
    
    This patch fixes the current SpotBugs issues along with some other minor
    cleanup spotted along the way. Either the SpotBugs issues were fixed or
    they were added to the excludeFilter as a special case.
    
    Follow on patches will enforce SpotBugs in the pre-commit build.
    
    Change-Id: I7f66176dcca9dbf77853b54bef20d947f3732e3f
    Reviewed-on: http://gerrit.cloudera.org:8080/14747
    Tested-by: Kudu Jenkins
    Reviewed-by: Adar Dembo <ad...@cloudera.com>
    Reviewed-by: Alexey Serbin <as...@cloudera.com>
---
 .../org/apache/kudu/gradle/DistTestTask.java       |   9 +-
 java/config/spotbugs/excludeFilter.xml             | 179 +++++++++++++++++++++
 java/gradle/quality.gradle                         |   2 +
 java/kudu-backup-tools/build.gradle                |   5 +
 .../apache/kudu/backup/TestKuduBackupLister.scala  |  24 +--
 .../org/apache/kudu/backup/KuduBackupRDD.scala     |   1 +
 .../org/apache/kudu/backup/TestKuduBackup.scala    |   8 +-
 .../tools/IntegrationTestBigLinkedList.java        |  18 ++-
 .../apache/kudu/mapreduce/tools/ITImportCsv.java   |  12 +-
 .../kudu/mapreduce/tools/ITImportParquet.java      |   6 -
 .../mapreduce/tools/ITImportParquetPreCheck.java   |   6 -
 .../main/java/org/apache/kudu/ColumnSchema.java    |   2 +-
 .../org/apache/kudu/client/AsyncKuduScanner.java   |   8 +-
 .../main/java/org/apache/kudu/client/Bytes.java    |   3 +-
 .../org/apache/kudu/client/KuduPartitioner.java    |  14 ++
 .../java/org/apache/kudu/client/KuduScanToken.java |  14 ++
 .../java/org/apache/kudu/client/RpcTraceFrame.java |   6 +-
 .../java/org/apache/kudu/client/ServerInfo.java    |   2 +-
 .../apache/kudu/client/ITScannerMultiTablet.java   |   2 +-
 .../apache/kudu/client/TestAsyncKuduSession.java   |   6 +-
 .../kudu/client/TestFlexiblePartitioning.java      |   6 +-
 .../org/apache/kudu/client/TestHybridTime.java     |   4 +-
 .../org/apache/kudu/client/TestKuduPredicate.java  |   2 +-
 .../java/org/apache/kudu/client/TestKuduTable.java |   2 +-
 .../org/apache/kudu/client/TestLeaderFailover.java |   2 +-
 .../org/apache/kudu/client/TestNegotiator.java     |   6 +-
 .../apache/kudu/client/TestPartitionPruner.java    |   2 +-
 .../java/org/apache/kudu/client/TestRowErrors.java |   2 +-
 .../java/org/apache/kudu/client/TestRowResult.java |   2 +-
 .../org/apache/kudu/client/TestScanPredicate.java  |  26 +--
 .../apache/kudu/client/TestScannerMultiTablet.java |   2 +-
 .../org/apache/kudu/client/TestStatistics.java     |   2 +-
 .../hive/metastore/TestKuduMetastorePlugin.java    |   2 +-
 java/kudu-jepsen/build.gradle                      |   6 +-
 .../java/org/apache/kudu/mapreduce/JarFinder.java  |   9 +-
 .../kudu/mapreduce/KuduTableMapReduceUtil.java     |  56 +++----
 .../kudu/mapreduce/HadoopTestingUtility.java       |   3 +-
 .../apache/kudu/mapreduce/ITInputFormatJob.java    |  10 +-
 .../apache/kudu/mapreduce/ITOutputFormatJob.java   |   6 +-
 .../org/apache/kudu/mapreduce/TestJarFinder.java   |  17 +-
 java/kudu-spark/build.gradle                       |   7 +-
 .../org/apache/kudu/spark/kudu/KuduContext.scala   |   6 +-
 .../scala/org/apache/kudu/spark/kudu/KuduRDD.scala |   1 +
 .../apache/kudu/spark/kudu/DefaultSourceTest.scala |   4 +-
 .../apache/kudu/spark/kudu/KuduContextTest.scala   |   5 +-
 .../org/apache/kudu/spark/kudu/KuduTestSuite.scala |   7 +-
 .../org/apache/kudu/spark/kudu/SparkSQLTest.scala  |  33 ++--
 .../org/apache/kudu/test/CapturingLogAppender.java |   4 +-
 .../kudu/test/CapturingToFileLogAppender.java      |   4 +-
 .../java/org/apache/kudu/test/ClientTestUtil.java  |   2 +-
 .../java/org/apache/kudu/test/KuduTestHarness.java |   4 +-
 .../kudu/test/cluster/KuduBinaryJarExtractor.java  |   3 +-
 .../apache/kudu/test/cluster/MiniKuduCluster.java  |  10 +-
 .../apache/kudu/test/junit/TestResultReporter.java |   5 +-
 54 files changed, 407 insertions(+), 182 deletions(-)

diff --git a/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java b/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java
index f05aacc..8b7065f 100644
--- a/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java
+++ b/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java
@@ -127,8 +127,7 @@ public class DistTestTask extends DefaultTask {
         File isolateFile = new File(outputDir, c + ".isolate");
         File isolatedFile = new File(outputDir, c + ".isolated");
         File genJsonFile = new File(outputDir, c + ".gen.json");
-
-        Files.write(genIsolate(outputDir.toPath(), t, c, baseDeps), isolateFile, UTF_8);
+        Files.asCharSink(isolateFile, UTF_8).write(genIsolate(outputDir.toPath(), t, c, baseDeps));
 
         // Write the gen.json
         GenJson gen = new GenJson();
@@ -137,7 +136,7 @@ public class DistTestTask extends DefaultTask {
             "-s", isolatedFile.toString());
         gen.dir = outputDir.toString();
         gen.name = c;
-        Files.write(GSON.toJson(gen), genJsonFile, UTF_8);
+        Files.asCharSink(genJsonFile, UTF_8).write(GSON.toJson(gen));
       }
     }
   }
@@ -284,7 +283,7 @@ public class DistTestTask extends DefaultTask {
   }
 
   private static class ClassNameCollectingProcessor implements TestClassProcessor {
-    public List<String> classNames = new ArrayList<String>();
+    public List<String> classNames = new ArrayList<>();
 
     @Override
     public void startProcessing(TestResultProcessor testResultProcessor) {
@@ -316,7 +315,7 @@ public class DistTestTask extends DefaultTask {
     private static class Variables {
       public List<String> files = new ArrayList<>();
       public List<String> command;
-    };
+    }
     Variables variables = new Variables();
 
     public String toJson() {
diff --git a/java/config/spotbugs/excludeFilter.xml b/java/config/spotbugs/excludeFilter.xml
new file mode 100644
index 0000000..dccb69d
--- /dev/null
+++ b/java/config/spotbugs/excludeFilter.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0"?>
+<!--
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+-->
+<FindBugsFilter>
+    <!-- General exclusions -->
+    <Match>
+        <!-- Ignore classes generated by Protobuf.
+        Unfortunately I couldn't find a way to universally filter all Protobuf classes. -->
+        <Or>
+            <Class name="~.*PB.*"/>
+            <Class name="~org\.apache\.kudu\.consensus\.Opid.*"/>
+            <Class name="~org\.apache\.kudu\.master\.Master.*"/>
+            <Class name="~org\.apache\.kudu\.rpc\.RpcHeader.*"/>
+        </Or>
+    </Match>
+    <Match>
+        <!-- Spotbugs works better with Java than with Scala. We suppress some categories of
+        bug reports when using Scala, since spotbugs generates huge numbers of false positives
+        when examining Scala code. -->
+         <Source name="~.*\.scala" />
+         <Or>
+             <!-- NP_LOAD_OF_KNOWN_NULL_VALUE: The variable referenced at this point is known to be
+              null due to an earlier check against null. -->
+             <Bug pattern="NP_LOAD_OF_KNOWN_NULL_VALUE"/>
+             <!-- NP_NULL_ON_SOME_PATH: Possible null pointer dereference. -->
+             <Bug pattern="NP_NULL_ON_SOME_PATH"/>
+             <!-- NP_NULL_PARAM_DEREF: Method call passes null for non-null parameter. -->
+             <Bug pattern="NP_NULL_PARAM_DEREF"/>
+             <!-- SE_BAD_FIELD: Non-transient non-serializable instance field in serializable class. -->
+             <Bug pattern="SE_BAD_FIELD"/>
+             <!-- SE_BAD_FIELD_STORE: Non-serializable value stored into instance field of a serializable class. -->
+             <Bug pattern="SE_BAD_FIELD_STORE"/>
+             <!-- DM_STRING_CTOR: Method invokes inefficient new String(String) constructor. -->
+             <Bug pattern="DM_STRING_CTOR"/>
+             <!-- DM_NEW_FOR_GETCLASS: Method allocates an object, only to get the class object. -->
+             <Bug pattern="DM_NEW_FOR_GETCLASS"/>
+             <!-- ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD: Write to static field from instance method. -->
+             <Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"/>
+             <!-- DM_NUMBER_CTOR: Method invokes inefficient Number constructor. -->
+             <Bug pattern="DM_NUMBER_CTOR"/>
+             <!-- RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE: Nullcheck of value previously dereferenced. -->
+             <Bug pattern="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"/>
+             <!-- RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE: Redundant nullcheck of value known to be non-null. -->
+             <Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/>
+             <!-- RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE: Redundant nullcheck of value known to be null. -->
+             <Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"/>
+             <!-- RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT: Return value of method without side effect is ignored. -->
+             <Bug pattern="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT"/>
+             <!-- NM_CLASS_NAMING_CONVENTION: Class names should start with an upper case letter. -->
+             <Bug pattern="NM_CLASS_NAMING_CONVENTION"/>
+             <!-- NM_METHOD_NAMING_CONVENTION: Method names should start with a lower case letter. -->
+             <Bug pattern="NM_METHOD_NAMING_CONVENTION"/>
+             <!-- EC_NULL_ARG: Call to equals(null) -->
+             <Bug pattern="EC_NULL_ARG"/>
+             <!-- NP_ALWAYS_NULL: Null pointer dereference -->
+             <Bug pattern="NP_ALWAYS_NULL"/>
+             <!-- MS_CANNOT_BE_FINAL: Field isn't final and can't be protected from malicious code. -->
+             <Bug pattern="MS_CANNOT_BE_FINAL"/>
+         </Or>
+    </Match>
+    <Match>
+        <!-- The retry rule doesn't need to be read.
+        This naming scheme should be used for all RetryRule usage to avoid SpotBugs issues.
+        -->
+        <Field name="~.*retryRule" />
+        <Bug pattern="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD" />
+    </Match>
+    <Match>
+        <!-- Disable warnings about mutable objects and the use of public fields.
+         Though these are important concerns, we have many instances of this warning
+         and "fixing" the warning could have performance implications. -->
+        <Bug pattern="EI_EXPOSE_REP,EI_EXPOSE_REP2" />
+    </Match>
+    <Match>
+        <!-- This rule often falsely flags side effecting calls. Tests will frequently call
+        methods for the side effects without caring about the return value. -->
+        <Class name="~org\.apache\.kudu.*Test.*"/>
+        <Bug pattern="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT" />
+    </Match>
+    <Match>
+        <!-- Tests use i % 2 == 1 frequently to alternate behavior. -->
+        <!-- TODO: converting these into negated "check for even" and remove. -->
+        <Class name="~org\.apache\.kudu.*Test.*"/>
+        <Bug pattern="IM_BAD_CHECK_FOR_ODD" />
+    </Match>
+
+    <!-- kudu-backup exclusions -->
+    <Match>
+        <!-- The options field doesn't need to be restored in this case. -->
+        <Class name="org.apache.kudu.backup.KuduBackupRDD"/>
+        <Field name="options" />
+        <Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED" />
+    </Match>
+
+    <!-- kudu-client exclusions -->
+    <Match>
+        <!-- Reference equality is intended here. -->
+        <Class name="org.apache.kudu.client.AsyncKuduClient"/>
+        <Method name="isMasterTable" />
+        <Bug pattern="ES_COMPARING_PARAMETER_STRING_WITH_EQ" />
+    </Match>
+    <Match>
+        <!-- These classes have exception in the name because they hold an exception. -->
+        <Or>
+            <Class name="org.apache.kudu.client.AuthzTokenCache$RpcAndException"/>
+            <Class name="org.apache.kudu.client.KuduException$OriginalException"/>
+        </Or>
+        <Bug pattern="NM_CLASS_NOT_EXCEPTION" />
+    </Match>
+
+    <Match>
+        <!-- The nullable annotation is from Guava and therefore can't be changed.
+        Guava is adding `@Nullable` on the parent `apply` method from the guava Predicate
+        implementation for `gtePred` and `ltPred` and that's being detected by SpotBugs for
+        some reason.
+        -->
+        <Class name="~org\.apache\.kudu\.client\.TestFlexiblePartitioning.*"/>
+        <Bug pattern="NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE" />
+    </Match>
+    <Match>
+        <!-- Adjusts AsyncKuduClient.FETCH_TABLETS_PER_RANGE_LOOKUP for testing purposes.  -->
+        <Class name="org.apache.kudu.client.TestScanToken"/>
+        <Method name="testScanTokens" />
+        <Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD" />
+    </Match>
+    <Match>
+        <!-- Adjusts TableLocationsCache.ticker for testing purposes.  -->
+        <Class name="org.apache.kudu.client.TestTableLocationsCache"/>
+        <Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD" />
+    </Match>
+
+    <!-- kudu-client-tools exclusions -->
+    <Match>
+        <!-- The rule doesn't need to be read. -->
+        <Class name="org.apache.kudu.mapreduce.tools.ITImportParquetPreCheck"/>
+        <Field name="chain" />
+        <Bug pattern="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD" />
+    </Match>
+
+    <!-- kudu-spark exclusions -->
+    <Match>
+        <!-- The options and projectedCols field doesn't need to be restored in this case. -->
+        <Class name="org.apache.kudu.spark.kudu.KuduRDD"/>
+        <Or>
+            <Field name="options" />
+            <Field name="projectedCols"/>
+        </Or>
+        <Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED" />
+    </Match>
+
+    <!-- kudu-test-utils exclusions -->
+    <Match>
+        <!-- There is nothing useful to do with the File.delete() return value. -->
+        <Class name="org.apache.kudu.test.CapturingToFileLogAppender"/>
+        <Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE" />
+    </Match>
+    <Match>
+        <!-- This is a mock for a test and doesn't need to be serialized. -->
+        <Class name="org.apache.kudu.test.junit.TestResultReporter$MockFlakyTestServlet"/>
+        <Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED" />
+    </Match>
+</FindBugsFilter>
\ No newline at end of file
diff --git a/java/gradle/quality.gradle b/java/gradle/quality.gradle
index 0b35cab..8db0798 100644
--- a/java/gradle/quality.gradle
+++ b/java/gradle/quality.gradle
@@ -42,6 +42,8 @@ spotbugs {
   toolVersion = versions.spotBugs
   ignoreFailures = true
   effort = "max"
+  reportLevel = "medium"
+  excludeFilter = file("$rootProject.projectDir/config/spotbugs/excludeFilter.xml")
 }
 
 tasks.withType(com.github.spotbugs.SpotBugsTask) {
diff --git a/java/kudu-backup-tools/build.gradle b/java/kudu-backup-tools/build.gradle
index c1eb612..4bf1021 100644
--- a/java/kudu-backup-tools/build.gradle
+++ b/java/kudu-backup-tools/build.gradle
@@ -41,4 +41,9 @@ dependencies {
 // kudu-backup-tools has no public Javadoc.
 javadoc {
   enabled = false
+}
+
+tasks.withType(com.github.spotbugs.SpotBugsTask) {
+  // This class causes SpotBugs runtime errors, so we completely ignore it from analysis.
+  classes = classes.filter { !it.path.contains("BaseTestKuduBackupCleaner") }
 }
\ No newline at end of file
diff --git a/java/kudu-backup-tools/src/test/scala/org/apache/kudu/backup/TestKuduBackupLister.scala b/java/kudu-backup-tools/src/test/scala/org/apache/kudu/backup/TestKuduBackupLister.scala
index e6dd8a6..9740434 100644
--- a/java/kudu-backup-tools/src/test/scala/org/apache/kudu/backup/TestKuduBackupLister.scala
+++ b/java/kudu-backup-tools/src/test/scala/org/apache/kudu/backup/TestKuduBackupLister.scala
@@ -68,7 +68,7 @@ abstract class BaseTestKuduBackupLister {
 
     val options = createOptions(rootPath, ListType.ALL)
     val stdout = new ByteArrayOutputStream
-    Console.withOut(new PrintStream(stdout)) {
+    Console.withOut(new PrintStream(stdout, false, "UTF-8")) {
       assertEquals(0, KuduBackupCLI.run(options))
     }
 
@@ -84,7 +84,7 @@ abstract class BaseTestKuduBackupLister {
       s"taco,id_taco,${endTime(1000)},0,1000,full",
       s"taco,id_taco,${endTime(2000)},100,2000,incremental"
     ).mkString("\n")
-    assertEquals(expected, stdout.toString.trim)
+    assertEquals(expected, stdout.toString("UTF-8").trim)
   }
 
   @Test
@@ -94,7 +94,7 @@ abstract class BaseTestKuduBackupLister {
 
     val options = createOptions(rootPath, ListType.LATEST)
     val stdout = new ByteArrayOutputStream
-    Console.withOut(new PrintStream(stdout)) {
+    Console.withOut(new PrintStream(stdout, false, "UTF-8")) {
       assertEquals(0, KuduBackupCLI.run(options))
     }
 
@@ -104,7 +104,7 @@ abstract class BaseTestKuduBackupLister {
       s"pizza,id_pizza,${endTime(600)},400,600,incremental",
       s"taco,id_taco,${endTime(2000)},100,2000,incremental"
     ).mkString("\n")
-    assertEquals(expected, stdout.toString.trim)
+    assertEquals(expected, stdout.toString("UTF-8").trim)
   }
 
   @Test
@@ -114,7 +114,7 @@ abstract class BaseTestKuduBackupLister {
 
     val options = createOptions(rootPath, ListType.RESTORE_SEQUENCE)
     val stdout = new ByteArrayOutputStream
-    Console.withOut(new PrintStream(stdout)) {
+    Console.withOut(new PrintStream(stdout, false, "UTF-8")) {
       assertEquals(0, KuduBackupCLI.run(options))
     }
 
@@ -129,7 +129,7 @@ abstract class BaseTestKuduBackupLister {
       s"taco,id_taco,${endTime(100)},0,100,full",
       s"taco,id_taco,${endTime(2000)},100,2000,incremental"
     ).mkString("\n")
-    assertEquals(expected, stdout.toString.trim)
+    assertEquals(expected, stdout.toString("UTF-8").trim)
   }
 
   @Test
@@ -139,7 +139,7 @@ abstract class BaseTestKuduBackupLister {
 
     val options = createOptions(rootPath, ListType.ALL, Seq("taco"))
     val stdout = new ByteArrayOutputStream
-    Console.withOut(new PrintStream(stdout)) {
+    Console.withOut(new PrintStream(stdout, false, "UTF-8")) {
       assertEquals(0, KuduBackupCLI.run(options))
     }
 
@@ -150,7 +150,7 @@ abstract class BaseTestKuduBackupLister {
       s"taco,id_taco,${endTime(1000)},0,1000,full",
       s"taco,id_taco,${endTime(2000)},100,2000,incremental"
     ).mkString("\n")
-    assertEquals(expected, stdout.toString.trim)
+    assertEquals(expected, stdout.toString("UTF-8").trim)
   }
 
   @Test
@@ -161,8 +161,8 @@ abstract class BaseTestKuduBackupLister {
     val options = createOptions(rootPath, ListType.ALL, Seq("pizza", "nope"))
     val stdout = new ByteArrayOutputStream
     val stderr = new ByteArrayOutputStream
-    Console.withOut(new PrintStream(stdout)) {
-      Console.withErr(new PrintStream(stderr)) {
+    Console.withOut(new PrintStream(stdout, false, "UTF-8")) {
+      Console.withErr(new PrintStream(stderr, false, "UTF-8")) {
         assertEquals(1, KuduBackupCLI.run(options))
       }
     }
@@ -174,9 +174,9 @@ abstract class BaseTestKuduBackupLister {
       s"pizza,id_pizza,${endTime(400)},200,400,incremental",
       s"pizza,id_pizza,${endTime(600)},400,600,incremental"
     ).mkString("\n")
-    assertEquals(expected, stdout.toString.trim)
+    assertEquals(expected, stdout.toString("UTF-8").trim)
 
-    assertEquals("No backups were found for 1 table(s):\nnope", stderr.toString.trim)
+    assertEquals("No backups were found for 1 table(s):\nnope", stderr.toString("UTF-8").trim)
   }
 
   def createOptions(
diff --git a/java/kudu-backup/src/main/scala/org/apache/kudu/backup/KuduBackupRDD.scala b/java/kudu-backup/src/main/scala/org/apache/kudu/backup/KuduBackupRDD.scala
index a9a7072..e15ee42 100644
--- a/java/kudu-backup/src/main/scala/org/apache/kudu/backup/KuduBackupRDD.scala
+++ b/java/kudu-backup/src/main/scala/org/apache/kudu/backup/KuduBackupRDD.scala
@@ -35,6 +35,7 @@ import scala.collection.JavaConverters._
 
 @InterfaceAudience.Private
 @InterfaceStability.Unstable
+@SerialVersionUID(1L)
 class KuduBackupRDD private[kudu] (
     @transient val table: KuduTable,
     @transient val options: BackupOptions,
diff --git a/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala b/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala
index 2e278bb..d802568 100644
--- a/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala
+++ b/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala
@@ -172,8 +172,8 @@ class TestKuduBackup extends KuduTestSuite {
     // table that does exist, it should not throw an exception, and it should return 1 to indicate
     // some error. The logs should contain a message about the missing table.
     val options = createBackupOptions(Seq("missingTable", tableName))
-    captureLogs(() => assertEquals(1, KuduBackup.run(options, ss)))
-      .contains("the table does not exist")
+    val logs = captureLogs(() => assertEquals(1, KuduBackup.run(options, ss)))
+    assertTrue(logs.contains("the table does not exist"))
 
     // Restore the backup of the non-failed table and validate the end result.
     restoreAndValidateTable(tableName, 100)
@@ -204,9 +204,9 @@ class TestKuduBackup extends KuduTestSuite {
 
     // There's no guarantee about the order restores run in, so it doesn't work to test fail-fast
     // and then the default no-fail-fast because the actual table may have been restored.
-    captureLogs(
+    val logs = captureLogs(
       () => assertEquals(1, runRestore(createRestoreOptions(Seq("missingTable", tableName)))))
-      .contains("Failed to restore table")
+    assertTrue(logs.contains("Failed to restore table"))
   }
 
   @Test
diff --git a/java/kudu-client-tools/src/main/java/org/apache/kudu/mapreduce/tools/IntegrationTestBigLinkedList.java b/java/kudu-client-tools/src/main/java/org/apache/kudu/mapreduce/tools/IntegrationTestBigLinkedList.java
index e3a1a48..07c20d6 100644
--- a/java/kudu-client-tools/src/main/java/org/apache/kudu/mapreduce/tools/IntegrationTestBigLinkedList.java
+++ b/java/kudu-client-tools/src/main/java/org/apache/kudu/mapreduce/tools/IntegrationTestBigLinkedList.java
@@ -356,7 +356,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
       public List<InputSplit> getSplits(JobContext job) throws IOException, InterruptedException {
         int numMappers = job.getConfiguration().getInt(GENERATOR_NUM_MAPPERS_KEY, 1);
 
-        ArrayList<InputSplit> splits = new ArrayList<InputSplit>(numMappers);
+        ArrayList<InputSplit> splits = new ArrayList<>(numMappers);
 
         for (int i = 0; i < numMappers; i++) {
           splits.add(new GeneratorInputSplit());
@@ -581,6 +581,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
       client.createTable(tableName, schema, builder);
     }
 
+    @SuppressWarnings("deprecation")
     public int runRandomInputGenerator(int numMappers, long numNodes, Path tmpOutput,
                                        Integer width, Integer wrapMultiplier) throws Exception {
       LOG.info("Running RandomInputGenerator with numMappers=" + numMappers +
@@ -607,6 +608,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
       return success ? 0 : 1;
     }
 
+    @SuppressWarnings("deprecation")
     public int runGenerator(int numMappers, long numNodes, int numTablets, Path tmpOutput,
                             Integer width, Integer wrapMultiplier) throws Exception {
       LOG.info("Running Generator with numMappers=" + numMappers + ", numNodes=" + numNodes);
@@ -667,6 +669,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
       private BytesWritable ref = new BytesWritable();
 
       @Override
+      @SuppressWarnings("unchecked")
       protected void map(NullWritable key, RowResult value, Mapper.Context context)
           throws IOException, InterruptedException {
         Bytes.setLong(rowKey, value.getLong(0));
@@ -688,7 +691,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
     }
 
     public static class VerifyReducer extends Reducer<BytesWritable,BytesWritable,Text,Text> {
-      private ArrayList<byte[]> refs = new ArrayList<byte[]>();
+      private ArrayList<byte[]> refs = new ArrayList<>();
 
       @Override
       public void reduce(BytesWritable key, Iterable<BytesWritable> values, Context context)
@@ -764,6 +767,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
       return run(new Path(outputDir), numReducers);
     }
 
+    @SuppressWarnings("deprecation")
     public int run(Path outputDir, int numReducers) throws Exception {
       LOG.info("Running Verify with outputDir=" + outputDir + ", numReducers=" + numReducers);
 
@@ -793,7 +797,6 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
       return success ? 0 : 1;
     }
 
-    @SuppressWarnings("deprecation")
     public boolean verify(long expectedReferenced) throws Exception {
       if (job == null) {
         throw new IllegalStateException("You should call run() first");
@@ -977,7 +980,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
         System.err.println();
         HelpFormatter formatter = new HelpFormatter();
         formatter.printHelp(getClass().getSimpleName(), options);
-        System.exit(-1);
+        throw new RuntimeException(e);
       }
 
       CommandLineParser cmdLineParser = new CommandLineParser(getConf());
@@ -1105,7 +1108,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
         do {
           if (headsCache.size() < numUpdatesPerMapper) {
             value = (RowResult)context.getCurrentValue();
-            headsCache.add(new Pair<Long, Long>(value.getLong(0), value.getLong(1)));
+            headsCache.add(new Pair<>(value.getLong(0), value.getLong(1)));
           }
         } while (context.nextKeyValue());
 
@@ -1240,6 +1243,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
       }
     }
 
+    @SuppressWarnings("deprecation")
     public int run(long maxLinkUpdatesPerMapper) throws Exception {
       LOG.info("Running Updater with maxLinkUpdatesPerMapper=" + maxLinkUpdatesPerMapper);
 
@@ -1464,7 +1468,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
   }
 
   private static void printCINodeString(CINode node) {
-    System.out.printf("%s:%s:%012d:%s:%s\n", node.key, node.prev, node.rowId, node.client,
+    System.out.printf("%s:%s:%012d:%s:%s%n", node.key, node.prev, node.rowId, node.client,
         node.updateCount);
   }
 
@@ -1487,7 +1491,7 @@ public class IntegrationTestBigLinkedList extends Configured implements Tool {
   private void usage() {
     System.err.println("Usage: " + this.getClass().getSimpleName() + " COMMAND [COMMAND options]");
     System.err.println("  where COMMAND is one of:");
-    System.err.println("");
+    System.err.println();
     System.err.println("  Generator                  A map only job that generates data.");
     System.err.println("  Verify                     A map reduce job that looks for holes");
     System.err.println("                             Look at the counts after running");
diff --git a/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportCsv.java b/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportCsv.java
index fc544c2..b39f799 100644
--- a/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportCsv.java
+++ b/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportCsv.java
@@ -118,11 +118,11 @@ public class ITImportCsv {
   }
 
   private void writeCsvFile(File data) throws IOException {
-    FileOutputStream fos = new FileOutputStream(data);
-    fos.write("1\t3\t2.3\tsome string\ttrue\n".getBytes(UTF_8));
-    fos.write("2\t5\t4.5\tsome more\tfalse\n".getBytes(UTF_8));
-    fos.write("3\t7\twait this is not a double\tbad row\ttrue\n".getBytes(UTF_8));
-    fos.write("4\t9\t10\ttrailing separator isn't bad mkay?\ttrue\t\n".getBytes(UTF_8));
-    fos.close();
+    try (FileOutputStream fos = new FileOutputStream(data)) {
+      fos.write("1\t3\t2.3\tsome string\ttrue\n".getBytes(UTF_8));
+      fos.write("2\t5\t4.5\tsome more\tfalse\n".getBytes(UTF_8));
+      fos.write("3\t7\twait this is not a double\tbad row\ttrue\n".getBytes(UTF_8));
+      fos.write("4\t9\t10\ttrailing separator isn't bad mkay?\ttrue\t\n".getBytes(UTF_8));
+    }
   }
 }
diff --git a/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquet.java b/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquet.java
index 23fdf50..a5752f9 100644
--- a/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquet.java
+++ b/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquet.java
@@ -102,12 +102,6 @@ public class ITImportParquet {
     Path data = new Path(testHome, "data.parquet");
     writeParquetFile(data,conf);
 
-    StringBuilder sb = new StringBuilder();
-    for (ColumnSchema col : schema.getColumns()) {
-      sb.append(col.getName());
-      sb.append(",");
-    }
-    sb.deleteCharAt(sb.length() - 1);
     String[] args = new String[] { "-D" + CommandLineParser.MASTER_ADDRESSES_KEY + "="
         + harness.getMasterAddressesAsString(), TABLE_NAME, data.toString()};
 
diff --git a/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquetPreCheck.java b/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquetPreCheck.java
index a3f7561..8120f8a 100644
--- a/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquetPreCheck.java
+++ b/java/kudu-client-tools/src/test/java/org/apache/kudu/mapreduce/tools/ITImportParquetPreCheck.java
@@ -109,12 +109,6 @@ public class ITImportParquetPreCheck {
     Path data = new Path(testHome, "data.parquet");
     writeParquetFile(data,conf);
 
-    StringBuilder sb = new StringBuilder();
-    for (ColumnSchema col : schema.getColumns()) {
-      sb.append(col.getName());
-      sb.append(",");
-    }
-    sb.deleteCharAt(sb.length() - 1);
     String[] args = new String[] { "-D" + CommandLineParser.MASTER_ADDRESSES_KEY + "=" +
       harness.getMasterAddressesAsString(), TABLE_NAME, data.toString()};
 
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java b/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java
index 7ae0335..81a352c 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/ColumnSchema.java
@@ -258,7 +258,7 @@ public class ColumnSchema {
   @InterfaceAudience.Public
   @InterfaceStability.Evolving
   public static class ColumnSchemaBuilder {
-    public static final List<Type> TYPES_WITH_ATTRIBUTES = Arrays.asList(Type.DECIMAL,
+    private static final List<Type> TYPES_WITH_ATTRIBUTES = Arrays.asList(Type.DECIMAL,
                                                                          Type.VARCHAR);
     private final String name;
     private final Type type;
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduScanner.java b/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduScanner.java
index 84368bd..9628bd2 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduScanner.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/AsyncKuduScanner.java
@@ -355,12 +355,12 @@ public final class AsyncKuduScanner {
    * @return a ColumnSchema for the virtual IS_DELETED column
    */
   private static ColumnSchema generateIsDeletedColumn(Schema schema) {
-    String columnName = DEFAULT_IS_DELETED_COL_NAME;
+    StringBuilder columnName = new StringBuilder(DEFAULT_IS_DELETED_COL_NAME);
     // If the column already exists and we need to pick an alternate column name.
-    while (schema.hasColumn(columnName)) {
-      columnName += "_";
+    while (schema.hasColumn(columnName.toString())) {
+      columnName.append("_");
     }
-    return new ColumnSchema.ColumnSchemaBuilder(columnName, Type.BOOL)
+    return new ColumnSchema.ColumnSchemaBuilder(columnName.toString(), Type.BOOL)
             .wireType(Common.DataType.IS_DELETED)
             .defaultValue(false)
             .nullable(false)
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/Bytes.java b/java/kudu-client/src/main/java/org/apache/kudu/client/Bytes.java
index 939d6ac..11572b5 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/Bytes.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/Bytes.java
@@ -29,6 +29,7 @@ package org.apache.kudu.client;
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
+import java.io.Serializable;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -1076,7 +1077,7 @@ public final class Bytes {
   public static final MemCmp MEMCMP = new MemCmp();
 
   /** {@link Comparator} for non-{@code null} byte arrays.  */
-  private static final class MemCmp implements Comparator<byte[]> {
+  private static final class MemCmp implements Comparator<byte[]>, Serializable {
 
     private MemCmp() {  // Can't instantiate outside of this class.
     }
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPartitioner.java b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPartitioner.java
index f282701..ea66d46 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPartitioner.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPartitioner.java
@@ -19,6 +19,7 @@ package org.apache.kudu.client;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import java.util.Arrays;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.NavigableMap;
@@ -160,6 +161,19 @@ public class KuduPartitioner {
     }
 
     @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (!(o instanceof BytesKey)) return false;
+      BytesKey bytesKey = (BytesKey) o;
+      return compareTo(bytesKey) == 0;
+    }
+
+    @Override
+    public int hashCode() {
+      return Arrays.hashCode(bytes);
+    }
+
+    @Override
     public String toString() {
       return Bytes.hex(bytes);
     }
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduScanToken.java b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduScanToken.java
index bfb0712..0b49e44 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduScanToken.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduScanToken.java
@@ -23,6 +23,7 @@ import java.util.EnumSet;
 import java.util.List;
 
 import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import com.google.protobuf.CodedInputStream;
 import com.google.protobuf.CodedOutputStream;
@@ -300,6 +301,19 @@ public class KuduScanToken implements Comparable<KuduScanToken> {
     return tablet.getPartition().compareTo(other.getTablet().getPartition());
   }
 
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof KuduScanToken)) return false;
+    KuduScanToken that = (KuduScanToken) o;
+    return compareTo(that) == 0;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(tablet, message);
+  }
+
   /**
    * Builds a sequence of scan tokens.
    */
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/RpcTraceFrame.java b/java/kudu-client/src/main/java/org/apache/kudu/client/RpcTraceFrame.java
index ac7f97e..73c726a 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/RpcTraceFrame.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/RpcTraceFrame.java
@@ -225,13 +225,13 @@ class RpcTraceFrame {
         maxTime, sentCount, receivedCount, delayedCount, masterRefreshCount, authRefreshCount,
         truncated));
     if (!sentTable.isEmpty()) {
-      sb.append(String.format("\n Sent: %s", tableToString(sentTable)));
+      sb.append(String.format("%n Sent: %s", tableToString(sentTable)));
     }
     if (!receivedTable.isEmpty()) {
-      sb.append(String.format("\n Received: %s", tableToString(receivedTable)));
+      sb.append(String.format("%n Received: %s", tableToString(receivedTable)));
     }
     if (!delayedTable.isEmpty()) {
-      sb.append(String.format("\n Delayed: %s", tableToString(delayedTable)));
+      sb.append(String.format("%n Delayed: %s", tableToString(delayedTable)));
     }
     return sb.toString();
   }
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java b/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java
index 1989794..911b223 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java
@@ -60,7 +60,7 @@ public class ServerInfo {
     Boolean isLocal = isLocalAddressCache.get(resolvedAddr);
     if (isLocal == null) {
       isLocal = NetUtil.isLocalAddress(resolvedAddr);
-      isLocalAddressCache.put(resolvedAddr, isLocal);
+      isLocalAddressCache.putIfAbsent(resolvedAddr, isLocal);
     }
     this.local = isLocal;
   }
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/ITScannerMultiTablet.java b/java/kudu-client/src/test/java/org/apache/kudu/client/ITScannerMultiTablet.java
index 0e01b08..dc38fab 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/ITScannerMultiTablet.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/ITScannerMultiTablet.java
@@ -41,7 +41,7 @@ public class ITScannerMultiTablet {
   protected static final int TABLET_COUNT = 3;
 
   private static Schema schema = getBasicSchema();
-  protected static KuduTable table;
+  protected KuduTable table;
 
   private static Random random = new Random(1234);
 
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduSession.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduSession.java
index 1099373..6286e78 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduSession.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduSession.java
@@ -44,9 +44,9 @@ public class TestAsyncKuduSession {
   private static final Schema SCHEMA = getBasicSchema();
   private static final String INJECTED_TS_ERROR = "injected error for test";
 
-  private static AsyncKuduClient client;
-  private static AsyncKuduSession session;
-  private static KuduTable table;
+  private AsyncKuduClient client;
+  private AsyncKuduSession session;
+  private KuduTable table;
 
   @Rule
   public KuduTestHarness harness = new KuduTestHarness();
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestFlexiblePartitioning.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestFlexiblePartitioning.java
index 517bb99..d1ce86a 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestFlexiblePartitioning.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestFlexiblePartitioning.java
@@ -139,7 +139,7 @@ public class TestFlexiblePartitioning {
       PartialRow lowerBound = schema.newPartialRow();
       minRow.fillPartialRow(lowerBound);
 
-      Set<Row> expected = Sets.filter(rows, minRow.gtePred());
+      Set<Row> expected = Sets.filter(rows, minRow.gtePred()::apply);
 
       KuduScanner scanner = client.newScannerBuilder(table).lowerBound(lowerBound).build();
       Set<Row> results = collectRows(scanner);
@@ -178,7 +178,7 @@ public class TestFlexiblePartitioning {
       PartialRow upperBound = schema.newPartialRow();
       maxRow.fillPartialRow(upperBound);
 
-      Set<Row> expected = Sets.filter(rows, Predicates.and(minRow.gtePred(), maxRow.ltPred()));
+      Set<Row> expected = Sets.filter(rows, Predicates.and(minRow.gtePred()::apply, maxRow.ltPred()));
 
       KuduScanner scanner = client.newScannerBuilder(table)
                                       .lowerBound(lowerBound)
@@ -222,7 +222,7 @@ public class TestFlexiblePartitioning {
       PartialRow upperBound = schema.newPartialRow();
       maxRow.fillPartialRow(upperBound);
 
-      Set<Row> expected = Sets.filter(rows, Predicates.and(minRow.gtePred(), maxRow.ltPred()));
+      Set<Row> expected = Sets.filter(rows, Predicates.and(minRow.gtePred()::apply, maxRow.ltPred()));
       Set<Row> results = new HashSet<>();
 
       for (LocatedTablet tablet : tablets) {
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestHybridTime.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestHybridTime.java
index 160d23b..f916987 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestHybridTime.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestHybridTime.java
@@ -55,7 +55,7 @@ public class TestHybridTime {
     TestHybridTime.class.getName() + "-" + System.currentTimeMillis();
 
   private static final Schema schema = getSchema();
-  private static KuduTable table;
+  private KuduTable table;
   private KuduClient client;
 
   private static final MiniKuduClusterBuilder clusterBuilder =
@@ -87,8 +87,6 @@ public class TestHybridTime {
    * future. The remaining writes should force an update to the server's clock and only increment
    * the logical value. Check that the client propagates the timestamp correctly by scanning
    * back the appropriate rows at the appropriate snapshots.
-   *
-   * @throws Exception
    */
   @Test(timeout = 100000)
   public void test() throws Exception {
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
index 760f9be..dd9c827 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
@@ -1222,7 +1222,7 @@ public class TestKuduPredicate {
   }
 
   @Test
-  public void TestDecimalCoercion() {
+  public void testDecimalCoercion() {
     Assert.assertEquals(
         KuduPredicate.newComparisonPredicate(decimal32Col, LESS, BigDecimal.valueOf(123)),
         KuduPredicate.newComparisonPredicate(decimal32Col, LESS, BigDecimal.valueOf(12300, 2))
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java
index 43758f4..643c55b 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java
@@ -792,7 +792,7 @@ public class TestKuduTable {
 
     // Insert some rows and test the statistics.
     KuduTableStatistics prevStatistics = new KuduTableStatistics(-1, -1);
-    KuduTableStatistics currentStatistics = new KuduTableStatistics(-1, -1);
+    KuduTableStatistics currentStatistics;
     KuduSession session = client.newSession();
     int num = 100;
     for (int i = 0; i < num; ++i) {
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java
index 78f722b..ecd33c0 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java
@@ -33,7 +33,7 @@ public class TestLeaderFailover {
 
   private static final String TABLE_NAME =
       TestLeaderFailover.class.getName() + "-" + System.currentTimeMillis();
-  private static KuduTable table;
+  private KuduTable table;
 
   @Rule
   public KuduTestHarness harness = new KuduTestHarness();
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestNegotiator.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestNegotiator.java
index 976512e..1b48d3a 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestNegotiator.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestNegotiator.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.security.KeyStore;
 import java.security.cert.Certificate;
@@ -118,8 +119,9 @@ public class TestNegotiator {
 
   KeyStore loadTestKeystore() throws Exception {
     KeyStore ks = KeyStore.getInstance("JKS");
-    ks.load(TestNegotiator.class.getResourceAsStream("/test-key-and-cert.jks"),
-        KEYSTORE_PASSWORD);
+    try (InputStream stream = TestNegotiator.class.getResourceAsStream("/test-key-and-cert.jks")) {
+      ks.load(stream, KEYSTORE_PASSWORD);
+    }
     return ks;
   }
 
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java
index c7b2e3b..fc8a68c 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java
@@ -676,7 +676,7 @@ public class TestPartitionPruner {
   }
 
   @Test
-  public void TestMultiColumnInListHashPruning() throws Exception {
+  public void testMultiColumnInListHashPruning() throws Exception {
     // CREATE TABLE t
     // (a INT8, b INT8, c INT8)
     // PRIMARY KEY (a, b, c)
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java
index c45d8e9..940ccbb 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java
@@ -36,7 +36,7 @@ public class TestRowErrors {
 
   private static final Schema basicSchema = getBasicSchema();
 
-  private static KuduTable table;
+  private KuduTable table;
 
   @Rule
   public KuduTestHarness harness = new KuduTestHarness();
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
index 16e1944..c5c3d99 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
@@ -44,7 +44,7 @@ public class TestRowResult {
 
   private static final Schema allTypesSchema = getSchemaWithAllTypes();
 
-  private static KuduTable table;
+  private KuduTable table;
 
   @Rule
   public KuduTestHarness harness = new KuduTestHarness();
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java
index e64ff44..d0173db 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestScanPredicate.java
@@ -294,7 +294,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -346,7 +346,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -359,7 +359,7 @@ public class TestScanPredicate {
     Schema schema = createTableSchema(Type.INT16);
     client.createTable("short-table", schema,
                            new CreateTableOptions().setRangePartitionColumns(
-                               ImmutableList.<String>of()));
+                               ImmutableList.of()));
     KuduTable table = client.openTable("short-table");
 
     NavigableSet<Long> values = createIntegerValues(Type.INT16);
@@ -373,7 +373,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -398,7 +398,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -411,7 +411,7 @@ public class TestScanPredicate {
     Schema schema = createTableSchema(Type.INT64);
     client.createTable("long-table", schema,
                            new CreateTableOptions().setRangePartitionColumns(
-                               ImmutableList.<String>of()));
+                               ImmutableList.of()));
     KuduTable table = client.openTable("long-table");
 
     NavigableSet<Long> values = createIntegerValues(Type.INT64);
@@ -425,7 +425,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -450,7 +450,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -476,7 +476,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -535,7 +535,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -598,7 +598,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -675,7 +675,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
@@ -734,7 +734,7 @@ public class TestScanPredicate {
       session.apply(insert);
     }
     Insert nullInsert = table.newInsert();
-    nullInsert.getRow().addLong("key", i++);
+    nullInsert.getRow().addLong("key", i);
     nullInsert.getRow().setNull("value");
     session.apply(nullInsert);
     session.flush();
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestScannerMultiTablet.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestScannerMultiTablet.java
index 9b9b648..9d742b2 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestScannerMultiTablet.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestScannerMultiTablet.java
@@ -49,7 +49,7 @@ public class TestScannerMultiTablet {
   /**
    * The timestamp after inserting the rows into the test table during setUp().
    */
-  private static long beforeWriteTimestamp;
+  private long beforeWriteTimestamp;
   private KuduTable table;
   private KuduClient client;
   private AsyncKuduClient asyncClient;
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestStatistics.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestStatistics.java
index 08e13b2..37a8ace 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestStatistics.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestStatistics.java
@@ -35,7 +35,7 @@ public class TestStatistics {
 
   private static final String TABLE_NAME = TestStatistics.class.getName() + "-"
       + System.currentTimeMillis();
-  private static KuduTable table;
+  private KuduTable table;
 
   @Rule
   public KuduTestHarness harness = new KuduTestHarness();
diff --git a/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java b/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
index e950c5b..07553b8 100644
--- a/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
+++ b/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
@@ -104,7 +104,7 @@ public class TestKuduMetastorePlugin {
         "jdbc:derby:memory:" + metadb.toString() + ";create=true");
     // Set the derby log file.
     Path derbyLogFile = hiveTestDir.resolve("derby.log");
-    derbyLogFile.toFile().createNewFile();
+    assertTrue(derbyLogFile.toFile().createNewFile());
     System.setProperty("derby.stream.error.file", derbyLogFile.toString());
 
     int msPort = MetaStoreUtils.startMetaStore(metastoreConf);
diff --git a/java/kudu-jepsen/build.gradle b/java/kudu-jepsen/build.gradle
index f03241c..9c87d4e 100644
--- a/java/kudu-jepsen/build.gradle
+++ b/java/kudu-jepsen/build.gradle
@@ -59,4 +59,8 @@ task runJepsen(type: JavaExec) {
 
 // We don't publish kudu-jepsen
 uploadArchives.enabled = false
-install.enabled = false
\ No newline at end of file
+install.enabled = false
+
+// SpotBugs doesn't work on Clojure.
+spotbugsMain.enabled = false
+spotbugsTest.enabled = false
\ No newline at end of file
diff --git a/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/JarFinder.java b/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/JarFinder.java
index 925e855..89ea0a7 100644
--- a/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/JarFinder.java
+++ b/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/JarFinder.java
@@ -74,6 +74,7 @@ public class JarFinder {
 
   public static void jarDir(File dir, String relativePath, ZipOutputStream zos)
       throws IOException {
+    Preconditions.checkNotNull(dir, "dir");
     Preconditions.checkNotNull(relativePath, "relativePath");
     Preconditions.checkNotNull(zos, "zos");
 
@@ -96,6 +97,9 @@ public class JarFinder {
   private static void zipDir(File dir, String relativePath, ZipOutputStream zos,
                              boolean start) throws IOException {
     String[] dirList = dir.list();
+    if (dirList == null) {
+      throw new RuntimeException("Could not list directory: " + dir);
+    }
     for (String aDirList : dirList) {
       File f = new File(dir, aDirList);
       if (!f.isHidden()) {
@@ -165,7 +169,10 @@ public class JarFinder {
             File testDir = getFileDir();
             testDir = testDir.getAbsoluteFile();
             if (!testDir.exists()) {
-              testDir.mkdirs();
+              if (!testDir.mkdirs()) {
+                throw new IOException(MessageFormat.format("could not create dir [{0}]",
+                    testDir));
+              }
             }
             File baseDir = new File(path);
             File tempJar = File.createTempFile("hadoop-", "", testDir);
diff --git a/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/KuduTableMapReduceUtil.java b/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/KuduTableMapReduceUtil.java
index 52b2fac..da4cb11 100644
--- a/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/KuduTableMapReduceUtil.java
+++ b/java/kudu-mapreduce/src/main/java/org/apache/kudu/mapreduce/KuduTableMapReduceUtil.java
@@ -1,21 +1,21 @@
-/**
- *
- * 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. See accompanying LICENSE file.
- */
-
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
 package org.apache.kudu.mapreduce;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.net.URL;
 import java.net.URLDecoder;
@@ -44,7 +44,6 @@ import org.apache.hadoop.mapreduce.Job;
 import org.apache.hadoop.mapreduce.TaskInputOutputContext;
 import org.apache.hadoop.security.Credentials;
 import org.apache.hadoop.security.token.Token;
-import org.apache.hadoop.security.token.TokenIdentifier;
 import org.apache.hadoop.util.StringUtils;
 import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.yetus.audience.InterfaceStability;
@@ -62,6 +61,7 @@ import org.apache.kudu.client.Operation;
  */
 @InterfaceAudience.Public
 @InterfaceStability.Evolving
+@SuppressWarnings("deprecation")
 public class KuduTableMapReduceUtil {
   // Mostly lifted from HBase's TableMapReduceUtil
 
@@ -206,6 +206,7 @@ public class KuduTableMapReduceUtil {
      * @param cacheBlocks whether the job should use scanners that cache blocks
      * @return this instance
      */
+    @SuppressWarnings("unchecked")
     public S cacheBlocks(boolean cacheBlocks) {
       this.cacheBlocks = cacheBlocks;
       return (S) this;
@@ -216,6 +217,7 @@ public class KuduTableMapReduceUtil {
      * @param isFaultTolerant whether the job should use fault tolerant scanners
      * @return this instance
      */
+    @SuppressWarnings("unchecked")
     public S isFaultTolerant(boolean isFaultTolerant) {
       this.isFaultTolerant = isFaultTolerant;
       return (S) this;
@@ -422,7 +424,7 @@ public class KuduTableMapReduceUtil {
     byte[] authnCreds = client.exportAuthenticationCredentials();
     Text service = new Text(client.getMasterAddressesAsString());
     job.getCredentials().addToken(AUTHN_CREDENTIALS_ALIAS,
-        new Token<TokenIdentifier>(null, authnCreds, KUDU_TOKEN_KIND, service));
+        new Token<>(null, authnCreds, KUDU_TOKEN_KIND, service));
   }
 
   /**
@@ -446,9 +448,6 @@ public class KuduTableMapReduceUtil {
     Text service = new Text(client.getMasterAddressesAsString());
     // Find the Hadoop credentials stored within the JAAS subject.
     Set<Credentials> credSet = subj.getPrivateCredentials(Credentials.class);
-    if (credSet == null) {
-      return;
-    }
     for (Credentials creds : credSet) {
       for (Token<?> tok : creds.getAllTokens()) {
         if (!tok.getKind().equals(KUDU_TOKEN_KIND)) {
@@ -502,13 +501,12 @@ public class KuduTableMapReduceUtil {
                                        Class<?>... classes) throws IOException {
 
     FileSystem localFs = FileSystem.getLocal(conf);
-    Set<String> jars = new HashSet<String>();
     // Add jars that are already in the tmpjars variable
-    jars.addAll(conf.getStringCollection("tmpjars"));
+    Set<String> jars = new HashSet<>(conf.getStringCollection("tmpjars"));
 
     // add jars as we find them to a map of contents jar name so that we can avoid
     // creating new jars for classes that have already been packaged.
-    Map<String, String> packagedClasses = new HashMap<String, String>();
+    Map<String, String> packagedClasses = new HashMap<>();
 
     // Add jars containing the specified classes
     for (Class<?> clazz : classes) {
@@ -567,7 +565,6 @@ public class KuduTableMapReduceUtil {
    * @param fs the FileSystem with which to qualify the returned path.
    * @param packagedClasses a map of class name to path.
    * @return a jar file that contains the class.
-   * @throws IOException
    */
   @SuppressWarnings("deprecation")
   private static Path findOrCreateJar(Class<?> myClass, FileSystem fs,
@@ -595,7 +592,6 @@ public class KuduTableMapReduceUtil {
    * the <code>packagedClasses</code> map.
    * @param myClass the class to find.
    * @return a jar file that contains the class, or null.
-   * @throws IOException
    */
   private static String findContainingJar(Class<?> myClass, Map<String, String> packagedClasses)
       throws IOException {
@@ -638,19 +634,13 @@ public class KuduTableMapReduceUtil {
     if (null == jar || jar.isEmpty()) {
       return;
     }
-    ZipFile zip = null;
-    try {
-      zip = new ZipFile(jar);
+    try (ZipFile zip = new ZipFile(jar)) {
       for (Enumeration<? extends ZipEntry> iter = zip.entries(); iter.hasMoreElements();) {
         ZipEntry entry = iter.nextElement();
         if (entry.getName().endsWith("class")) {
           packagedClasses.put(entry.getName(), jar);
         }
       }
-    } finally {
-      if (null != zip) {
-        zip.close();
-      }
     }
   }
 }
diff --git a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/HadoopTestingUtility.java b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/HadoopTestingUtility.java
index e9cdf06..e550325 100644
--- a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/HadoopTestingUtility.java
+++ b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/HadoopTestingUtility.java
@@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.junit.Assert;
 
 /**
  * This class is analog to HBaseTestingUtility except that we only need it for the MR tests.
@@ -67,7 +68,7 @@ public class HadoopTestingUtility {
     }
     Path testPath = new Path(getBaseTestDir(), testName + System.currentTimeMillis());
     this.testDir = new File(testPath.toString()).getAbsoluteFile();
-    this.testDir.mkdirs();
+    Assert.assertTrue(this.testDir.mkdirs());
     // Set this property so when mapreduce jobs run, they will use this as their home dir.
     System.setProperty("test.build.dir", this.testDir.toString());
     System.setProperty("hadoop.home.dir", this.testDir.toString());
diff --git a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITInputFormatJob.java b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITInputFormatJob.java
index 2808ed9..608c678 100644
--- a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITInputFormatJob.java
+++ b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITInputFormatJob.java
@@ -21,7 +21,6 @@ import static org.apache.kudu.test.KuduTestHarness.DEFAULT_SLEEP;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -65,15 +64,14 @@ public class ITInputFormatJob {
   }
 
   @Test
-  @SuppressWarnings("deprecation")
   public void test() throws Exception {
 
     createFourTabletsTableWithNineRows(harness.getAsyncClient(), TABLE_NAME, DEFAULT_SLEEP);
 
     JobConf conf = new JobConf();
-    HADOOP_UTIL.setupAndGetTestDir(ITInputFormatJob.class.getName(), conf).getAbsolutePath();
+    HADOOP_UTIL.setupAndGetTestDir(ITInputFormatJob.class.getName(), conf);
 
-    createAndTestJob(conf, new ArrayList<KuduPredicate>(), 9);
+    createAndTestJob(conf, new ArrayList<>(), 9);
 
     KuduPredicate pred1 = KuduPredicate.newComparisonPredicate(
         basicSchema.getColumnByIndex(0), KuduPredicate.ComparisonOp.GREATER_EQUAL, 20);
@@ -84,6 +82,7 @@ public class ITInputFormatJob {
     createAndTestJob(conf, Lists.newArrayList(pred1, pred2), 2);
   }
 
+  @SuppressWarnings("deprecation")
   private void createAndTestJob(JobConf conf,
                                 List<KuduPredicate> predicates, int expectedCount)
       throws Exception {
@@ -123,8 +122,7 @@ public class ITInputFormatJob {
       Mapper<NullWritable, RowResult, NullWritable, NullWritable> {
 
     @Override
-    protected void map(NullWritable key, RowResult value, Context context) throws IOException,
-        InterruptedException {
+    protected void map(NullWritable key, RowResult value, Context context) {
       context.getCounter(Counters.ROWS).increment(1);
       LOG.info(value.toStringLongFormat()); // useful to visual debugging
     }
diff --git a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITOutputFormatJob.java b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITOutputFormatJob.java
index ba3682e..742ae57 100644
--- a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITOutputFormatJob.java
+++ b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/ITOutputFormatJob.java
@@ -135,8 +135,8 @@ public class ITOutputFormatJob {
   }
 
   private void writeDataFile(File data) throws IOException {
-    FileOutputStream fos = new FileOutputStream(data);
-    fos.write("VALUE1\nVALUE2\n".getBytes(UTF_8));
-    fos.close();
+    try (FileOutputStream fos = new FileOutputStream(data)) {
+      fos.write("VALUE1\nVALUE2\n".getBytes(UTF_8));
+    }
   }
 }
diff --git a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/TestJarFinder.java b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/TestJarFinder.java
index f6e5d7b..50c7443 100644
--- a/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/TestJarFinder.java
+++ b/java/kudu-mapreduce/src/test/java/org/apache/kudu/mapreduce/TestJarFinder.java
@@ -45,7 +45,7 @@ import org.apache.kudu.test.junit.RetryRule;
  */
 public class TestJarFinder {
 
-  private static File testDir;
+  private File testDir;
 
   @Rule
   public RetryRule retryRule = new RetryRule();
@@ -58,7 +58,9 @@ public class TestJarFinder {
 
   @After
   public void tearDown() throws Exception {
-    FileUtils.deleteDirectory(testDir);
+    if (testDir != null) {
+      FileUtils.deleteDirectory(testDir);
+    }
   }
 
   @Test
@@ -81,12 +83,13 @@ public class TestJarFinder {
     File dir = new File(testDir,
       TestJarFinder.class.getName() + "-testExistingManifest");
     File metaInfDir = new File(dir, "META-INF");
-    metaInfDir.mkdirs();
+    Assert.assertTrue(metaInfDir.mkdirs());
     File manifestFile = new File(metaInfDir, "MANIFEST.MF");
     Manifest manifest = new Manifest();
-    OutputStream os = new FileOutputStream(manifestFile);
-    manifest.write(os);
-    os.close();
+
+    try (OutputStream os = new FileOutputStream(manifestFile)) {
+      manifest.write(os);
+    }
 
     File propsFile = new File(dir, "props.properties");
     Writer writer = Files.newBufferedWriter(propsFile.toPath(), UTF_8);
@@ -105,7 +108,7 @@ public class TestJarFinder {
   public void testNoManifest() throws Exception {
     File dir = new File(testDir,
       TestJarFinder.class.getName() + "-testNoManifest");
-    dir.mkdirs();
+    Assert.assertTrue(dir.mkdirs());
     File propsFile = new File(dir, "props.properties");
     Writer writer = Files.newBufferedWriter(propsFile.toPath(), UTF_8);
     new Properties().store(writer, "");
diff --git a/java/kudu-spark/build.gradle b/java/kudu-spark/build.gradle
index 6c8e833..17992a5 100644
--- a/java/kudu-spark/build.gradle
+++ b/java/kudu-spark/build.gradle
@@ -38,4 +38,9 @@ dependencies {
 }
 
 // Adjust the artifact name to include the spark and scala base versions.
-archivesBaseName = "kudu-spark${versions.sparkBase}_${versions.scalaBase}"
\ No newline at end of file
+archivesBaseName = "kudu-spark${versions.sparkBase}_${versions.scalaBase}"
+
+tasks.withType(com.github.spotbugs.SpotBugsTask) {
+  // This class causes SpotBugs runtime errors, so we completely ignore it from analysis.
+  classes = classes.filter { !it.path.contains("SparkSQLTest") }
+}
\ No newline at end of file
diff --git a/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduContext.scala b/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduContext.scala
index a27a1e7..c3d426d 100644
--- a/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduContext.scala
+++ b/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduContext.scala
@@ -58,6 +58,7 @@ import org.apache.kudu.Type
  */
 @InterfaceAudience.Public
 @InterfaceStability.Evolving
+@SerialVersionUID(1L)
 class KuduContext(val kuduMaster: String, sc: SparkContext, val socketReadTimeoutMs: Option[Long])
     extends Serializable {
   val log: Logger = LoggerFactory.getLogger(getClass)
@@ -129,7 +130,7 @@ class KuduContext(val kuduMaster: String, sc: SparkContext, val socketReadTimeou
   val durationHistogram = new HdrHistogramAccumulator()
   sc.register(durationHistogram, "kudu.write_duration")
 
-  @Deprecated()
+  @deprecated("Use KuduContext constructor", "1.4.0")
   def this(kuduMaster: String) {
     this(kuduMaster, new SparkContext())
   }
@@ -268,7 +269,8 @@ class KuduContext(val kuduMaster: String, sc: SparkContext, val socketReadTimeou
    * @param tableName the Kudu table to insert into
    */
   @deprecated(
-    "Use KuduContext.insertRows(data, tableName, new KuduWriteOptions(ignoreDuplicateRowErrors = true))")
+    "Use KuduContext.insertRows(data, tableName, new KuduWriteOptions(ignoreDuplicateRowErrors = true))",
+    "1.8.0")
   def insertIgnoreRows(data: DataFrame, tableName: String): Unit = {
     val writeOptions = KuduWriteOptions(ignoreDuplicateRowErrors = true)
     log.info(s"inserting into table '$tableName'")
diff --git a/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduRDD.scala b/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduRDD.scala
index 52bcba8..ca57f13 100644
--- a/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduRDD.scala
+++ b/java/kudu-spark/src/main/scala/org/apache/kudu/spark/kudu/KuduRDD.scala
@@ -36,6 +36,7 @@ import org.apache.kudu.client.KuduScannerIterator.NextRowsCallback
  */
 @InterfaceAudience.Public
 @InterfaceStability.Evolving
+@SerialVersionUID(1L)
 class KuduRDD private[kudu] (
     val kuduContext: KuduContext,
     @transient val table: KuduTable,
diff --git a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/DefaultSourceTest.scala b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/DefaultSourceTest.scala
index 2f7ddb1..6dca719 100644
--- a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/DefaultSourceTest.scala
+++ b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/DefaultSourceTest.scala
@@ -62,7 +62,7 @@ class DefaultSourceTest extends KuduTestSuite with Matchers {
    * syntax still works. This should be removed when the
    * deprecated `kudu` methods are removed.
    */
-  @Test
+  @Test @deprecated("Marked as deprecated to suppress warning", "")
   def testPackageReaderAndWriter(): Unit = {
     val df = sqlContext.read.options(kuduOptions).kudu
     val baseDF = df.limit(1) // filter down to just the first row
@@ -276,7 +276,7 @@ class DefaultSourceTest extends KuduTestSuite with Matchers {
     deleteRow(100)
   }
 
-  @Test
+  @Test @deprecated("Marked as deprecated to suppress warning", "")
   def testInsertIgnoreRowsMethod() {
     val df = sqlContext.read.options(kuduOptions).format("kudu").load
     val baseDF = df.limit(1) // filter down to just the first row
diff --git a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduContextTest.scala b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduContextTest.scala
index b322532..80cbbb2 100644
--- a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduContextTest.scala
+++ b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduContextTest.scala
@@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream
 import java.io.ObjectInputStream
 import java.io.ObjectOutputStream
 import java.math.BigDecimal
+import java.nio.charset.StandardCharsets.UTF_8
 import java.sql.Timestamp
 
 import org.apache.kudu.util.TimestampUtil
@@ -98,7 +99,7 @@ class KuduContextTest extends KuduTestSuite with Matchers {
       assert(r.apply(5).asInstanceOf[Boolean] == (rows.apply(index)._2 % 2 == 1))
       assert(r.apply(6).asInstanceOf[Short] == rows.apply(index)._2.toShort)
       assert(r.apply(7).asInstanceOf[Float] == rows.apply(index)._2.toFloat)
-      val binaryBytes = s"bytes ${rows.apply(index)._2}".getBytes().toSeq
+      val binaryBytes = s"bytes ${rows.apply(index)._2}".getBytes(UTF_8).toSeq
       assert(r.apply(8).asInstanceOf[Array[Byte]].toSeq == binaryBytes)
       assert(
         r.apply(9).asInstanceOf[Timestamp] ==
@@ -125,7 +126,7 @@ class KuduContextTest extends KuduTestSuite with Matchers {
       .first
       .get(0)
       .asInstanceOf[Array[Byte]]
-      .shouldBe("bytes 0".getBytes)
+      .shouldBe("bytes 0".getBytes(UTF_8))
     // decode the binary to string and compare
     dataDF
       .sort("key")
diff --git a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduTestSuite.scala b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduTestSuite.scala
index 8dbe53f..46293db 100644
--- a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduTestSuite.scala
+++ b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/KuduTestSuite.scala
@@ -17,6 +17,7 @@
 package org.apache.kudu.spark.kudu
 
 import java.math.BigDecimal
+import java.nio.charset.StandardCharsets.UTF_8
 import java.util.Date
 
 import scala.collection.JavaConverters._
@@ -38,7 +39,7 @@ import org.apache.spark.sql.SparkSession
 import org.junit.After
 import org.junit.Before
 import org.junit.Rule
-import org.scalatest.junit.JUnitSuite
+import org.scalatestplus.junit.JUnitSuite
 
 import scala.annotation.meta.getter
 
@@ -175,7 +176,7 @@ trait KuduTestSuite extends JUnitSuite {
       row.addBoolean(5, i % 2 == 1)
       row.addShort(6, i.toShort)
       row.addFloat(7, i.toFloat)
-      row.addBinary(8, s"bytes $i".getBytes())
+      row.addBinary(8, s"bytes $i".getBytes(UTF_8))
       val ts = System.currentTimeMillis() * 1000
       row.addLong(9, ts)
       row.addByte(10, i.toByte)
@@ -216,7 +217,7 @@ trait KuduTestSuite extends JUnitSuite {
       row.addBoolean(5, i % 2 == 1)
       row.addShort(6, i.toShort)
       row.addFloat(7, i.toFloat)
-      row.addBinary(8, (s"*" * rowDataSize).getBytes())
+      row.addBinary(8, (s"*" * rowDataSize).getBytes(UTF_8))
       val ts = System.currentTimeMillis() * 1000
       row.addLong(9, ts)
       row.addByte(10, i.toByte)
diff --git a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/SparkSQLTest.scala b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/SparkSQLTest.scala
index a6aaf41..e4982e3 100644
--- a/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/SparkSQLTest.scala
+++ b/java/kudu-spark/src/test/scala/org/apache/kudu/spark/kudu/SparkSQLTest.scala
@@ -197,7 +197,6 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
     keys.foreach { key =>
       val insert = testTable.newInsert
       val row = insert.getRow
-      val r = Array(1, 2, 3)
       row.addString(0, key)
       kuduSession.apply(insert)
     }
@@ -234,7 +233,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
     results = sqlContext
       .sql("SELECT key FROM " + tableName + " where key IS NULL")
       .collectAsList()
-    assert(results.isEmpty())
+    assert(results.isEmpty)
   }
 
   @Test
@@ -318,7 +317,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateDouble() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i > 5 },
+      rows.count { case (_, i, _, _) => i > 5 },
       sqlContext
         .sql(s"""SELECT key, c3_double FROM $tableName where c3_double > "5.0"""")
         .count())
@@ -327,7 +326,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateLong() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i > 5 },
+      rows.count { case (_, i, _, _) => i > 5 },
       sqlContext
         .sql(s"""SELECT key, c4_long FROM $tableName where c4_long > "5"""")
         .count())
@@ -336,7 +335,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateBool() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i % 2 == 0 },
+      rows.count { case (_, i, _, _) => i % 2 == 0 },
       sqlContext
         .sql(s"""SELECT key, c5_bool FROM $tableName where c5_bool = true""")
         .count())
@@ -345,7 +344,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateShort() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i > 5 },
+      rows.count { case (_, i, _, _) => i > 5 },
       sqlContext
         .sql(s"""SELECT key, c6_short FROM $tableName where c6_short > 5""")
         .count())
@@ -355,7 +354,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateFloat() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i > 5 },
+      rows.count { case (_, i, _, _) => i > 5 },
       sqlContext
         .sql(s"""SELECT key, c7_float FROM $tableName where c7_float > 5""")
         .count())
@@ -365,7 +364,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateDecimal32() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i > 5 },
+      rows.count { case (_, i, _, _) => i > 5 },
       sqlContext
         .sql(s"""SELECT key, c11_decimal32 FROM $tableName where c11_decimal32 > 5""")
         .count())
@@ -374,7 +373,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateDecimal64() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i > 5 },
+      rows.count { case (_, i, _, _) => i > 5 },
       sqlContext
         .sql(s"""SELECT key, c12_decimal64 FROM $tableName where c12_decimal64 > 5""")
         .count())
@@ -383,7 +382,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicateDecimal128() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => i > 5 },
+      rows.count { case (_, i, _, _) => i > 5 },
       sqlContext
         .sql(s"""SELECT key, c13_decimal128 FROM $tableName where c13_decimal128 > 5""")
         .count())
@@ -392,13 +391,13 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
   @Test
   def testTableScanWithProjectionAndPredicate() {
     assertEquals(
-      rows.count { case (key, i, s, ts) => s != null && s > "5" },
+      rows.count { case (_, _, s, _) => s != null && s > "5" },
       sqlContext
         .sql(s"""SELECT key FROM $tableName where c2_s > "5"""")
         .count())
 
     assertEquals(
-      rows.count { case (key, i, s, ts) => s != null },
+      rows.count { case (_, _, s, _) => s != null },
       sqlContext
         .sql(s"""SELECT key, c2_s FROM $tableName where c2_s IS NOT NULL""")
         .count())
@@ -493,7 +492,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
       new CreateTableOptions()
         .setRangePartitionColumns(List("key").asJava)
         .setNumReplicas(1))
-    var options1: Map[String, String] =
+    val options1: Map[String, String] =
       Map("kudu.table" -> table1, "kudu.master" -> harness.getMasterAddressesAsString)
     df.write.options(options1).mode("append").format("kudu").save
     val df1 = sqlContext.read.options(options1).format("kudu").load
@@ -507,7 +506,7 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
       new CreateTableOptions()
         .setRangePartitionColumns(List("key").asJava)
         .setNumReplicas(1))
-    var options2: Map[String, String] =
+    val options2: Map[String, String] =
       Map("kudu.table" -> table2, "kudu.master" -> harness.getMasterAddressesAsString)
     df.write.options(options2).mode("append").format("kudu").save
     val df2 = sqlContext.read.options(options2).format("kudu").load
@@ -521,14 +520,14 @@ class SparkSQLTest extends KuduTestSuite with Matchers {
 
     // 3. Test join with table size should be able to broadcast.
     val sqlStr = s"SELECT * FROM $table1 JOIN $table2 ON $table1.key = $table2.key"
-    var physical = sqlContext.sql(sqlStr).queryExecution.sparkPlan
-    var operators = physical.collect {
+    val physical = sqlContext.sql(sqlStr).queryExecution.sparkPlan
+    val operators = physical.collect {
       case j: BroadcastHashJoinExec => j
     }
     assert(operators.size == 1)
 
     // Verify result.
-    var results = sqlContext.sql(sqlStr).collectAsList()
+    val results = sqlContext.sql(sqlStr).collectAsList()
     assert(results.size() == rowCount)
   }
 }
diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingLogAppender.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingLogAppender.java
index 9227016..87224b0 100644
--- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingLogAppender.java
+++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingLogAppender.java
@@ -43,6 +43,8 @@ public class CapturingLogAppender extends AbstractAppender {
       .withPattern("%d{HH:mm:ss.SSS} [%p - %t] (%F:%L) %m%n")
       .build();
 
+  private static final Random RANDOM = new Random();
+
   // The caller should detach the logger before calling getAppendedText().
   // Nevertheless, for some reason it is still possible for additional
   // append() calls to happen _after_ the logger is detached, which may race
@@ -53,7 +55,7 @@ public class CapturingLogAppender extends AbstractAppender {
   public CapturingLogAppender() {
     // Appender name must be unique so that attaching/detaching works correctly
     // when multiple capturing appenders are used recursively.
-    super(String.format("CapturingToFileLogAppender-%d", new Random().nextInt()),
+    super(String.format("CapturingToFileLogAppender-%d", RANDOM.nextInt()),
           /* filter */ null, LAYOUT, /* ignoreExceptions */ true, Property.EMPTY_ARRAY);
 
     // If we don't call start(), we get an ugly log error:
diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingToFileLogAppender.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingToFileLogAppender.java
index 7a63dcc..f71497a 100644
--- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingToFileLogAppender.java
+++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/CapturingToFileLogAppender.java
@@ -58,6 +58,8 @@ public class CapturingToFileLogAppender extends AbstractAppender implements Auto
       .withPattern("%d{HH:mm:ss.SSS} [%p - %t] (%F:%L) %m%n")
       .build();
 
+  private static final Random RANDOM = new Random();
+
   private File outputFile;
   private Writer outputFileWriter;
 
@@ -72,7 +74,7 @@ public class CapturingToFileLogAppender extends AbstractAppender implements Auto
   public CapturingToFileLogAppender(boolean useGzip) throws IOException {
     // Appender name must be unique so that attaching/detaching works correctly
     // when multiple capturing appenders are used recursively.
-    super(String.format("CapturingToFileLogAppender-%d", new Random().nextInt()),
+    super(String.format("CapturingToFileLogAppender-%d", RANDOM.nextInt()),
           /* filter */ null, LAYOUT, /* ignoreExceptions */ true, Property.EMPTY_ARRAY);
 
     outputFile = File.createTempFile("captured_output", ".txt.gz");
diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/ClientTestUtil.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/ClientTestUtil.java
index c4fce18..363e9eb 100644
--- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/ClientTestUtil.java
+++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/ClientTestUtil.java
@@ -171,7 +171,7 @@ public abstract class ClientTestUtil {
           }
         }
       });
-      thread.run();
+      thread.start();
       threads.add(thread);
     }
 
diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/KuduTestHarness.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/KuduTestHarness.java
index 7b2834a..dba80aa 100644
--- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/KuduTestHarness.java
+++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/KuduTestHarness.java
@@ -179,9 +179,10 @@ public class KuduTestHarness extends ExternalResource {
    * @param table a KuduTable which will get its single tablet's leader killed.
    * @throws Exception
    */
+  @SuppressWarnings("deprecation")
   public void killTabletLeader(KuduTable table) throws Exception {
     List<LocatedTablet> tablets = table.getTabletsLocations(DEFAULT_SLEEP);
-    if (tablets.isEmpty() || tablets.size() > 1) {
+    if (tablets.size() != 1) {
       fail("Currently only support killing leaders for tables containing 1 tablet, table " +
           table.getName() + " has " + tablets.size());
     }
@@ -272,6 +273,7 @@ public class KuduTestHarness extends ExternalResource {
    * @param table table to query for a TS to restart
    * @throws Exception
    */
+  @SuppressWarnings("deprecation")
   public void restartTabletServer(KuduTable table) throws Exception {
     List<LocatedTablet> tablets = table.getTabletsLocations(DEFAULT_SLEEP);
     if (tablets.isEmpty()) {
diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryJarExtractor.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryJarExtractor.java
index 69aec0e..e062724 100644
--- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryJarExtractor.java
+++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryJarExtractor.java
@@ -182,7 +182,8 @@ public class KuduBinaryJarExtractor {
           Path newFile = Paths.get(target.toString(), file.toString());
           Files.copy(file, newFile, StandardCopyOption.REPLACE_EXISTING);
 
-          if (file.getParent().endsWith("bin")) {
+          Path parent = file.getParent();
+          if (parent != null && parent.endsWith("bin")) {
             Set<PosixFilePermission> perms = Files.getPosixFilePermissions(newFile);
             perms.add(PosixFilePermission.OWNER_EXECUTE);
             Files.setPosixFilePermissions(newFile, perms);
diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java
index ff5a15a..a61a78c 100644
--- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java
+++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java
@@ -176,7 +176,7 @@ public class MiniKuduCluster implements AutoCloseable {
    * Starts this Kudu cluster.
    * @throws IOException if something went wrong in transit
    */
-  private void start() throws IOException {
+  private synchronized void start() throws IOException {
     Preconditions.checkArgument(numMasters > 0, "Need at least one master");
 
     // Start the control shell and the communication channel to it.
@@ -287,14 +287,14 @@ public class MiniKuduCluster implements AutoCloseable {
    * @return the list of master servers
    */
   public List<HostAndPort> getMasterServers() {
-    return new ArrayList(masterServers.keySet());
+    return new ArrayList<>(masterServers.keySet());
   }
 
   /**
    * @return the list of tablet servers
    */
   public List<HostAndPort> getTabletServers() {
-    return new ArrayList(tabletServers.keySet());
+    return new ArrayList<>(tabletServers.keySet());
   }
 
   /**
@@ -481,8 +481,6 @@ public class MiniKuduCluster implements AutoCloseable {
         .build());
   }
 
-
-  /** {@override} */
   @Override
   public void close() {
     shutdown();
@@ -491,7 +489,7 @@ public class MiniKuduCluster implements AutoCloseable {
   /**
    * Shuts down a Kudu cluster.
    */
-  public void shutdown() {
+  public synchronized void shutdown() {
     // Closing stdin should cause the control shell process to terminate.
     if (miniClusterStdin != null) {
       try {
diff --git a/java/kudu-test-utils/src/test/java/org/apache/kudu/test/junit/TestResultReporter.java b/java/kudu-test-utils/src/test/java/org/apache/kudu/test/junit/TestResultReporter.java
index 1adf77d..7028d40 100644
--- a/java/kudu-test-utils/src/test/java/org/apache/kudu/test/junit/TestResultReporter.java
+++ b/java/kudu-test-utils/src/test/java/org/apache/kudu/test/junit/TestResultReporter.java
@@ -100,9 +100,10 @@ public class TestResultReporter {
    */
   private static class MockFlakyTestServlet extends HttpServlet {
     private static final Logger LOG = LoggerFactory.getLogger(MockFlakyTestServlet.class);
-    private final List<TestRecord> records = new ArrayList<>();
+    private static final long serialVersionUID = 1L;
+    private transient final List<TestRecord> records = new ArrayList<>();
 
-    public List<TestRecord> getRecords() {
+    List<TestRecord> getRecords() {
       return records;
     }