Skip to content
Java Reflection and Unsafe Alternates - MethodHandle and VarHandle API - Fix broken tests in a Code Kata
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
_layouts
docs
src
.gitignore
CONTRIBUTING.md
LICENSE
README.md
pom.xml

README.md

Method Reflection and Unsafe alternates Kata

DaVinci Machine Project

Table of Contents

Many Java libraries and frameworks currently use Reflection and Unsafe APIs. With the newer modular Java some of these important tools of our trade may become incompatible and/or may not work as desired. In addition several enterprise applications also rely on Core Reflection, (if not the use of Unsafe APIs).

What is a Code-Kata

A code-kata is a coding exercise that builds muscle memory by a practice of programming to arrive at a known solution.

How does one go about with this code kata?

The essence of the exercise (presentation material and code kata) is to demonstrate the alternates for the current usage patterns for some of the simpler and more common usages of Java Reflection API and the sun.misc.Unsafe among applications, libraries and frameworks. An explanation of the newer Handles API will be followed with code that allows for a comparison between using both styles.

This set of code katas rely on fixing broken tests. The tests may have multiple solutions, the intent is to learn and experiment.

The project contains several JUnit tests that fail with a message "Test Failure - Fix all TODOs. ".

Here are simple steps to use this kata:

  1. Run the test class(es).
  2. One or more tests will fail with the test failure message, phrased above.
  3. Fix the failing tests by taking hints from the TODOs.
  4. Repeat above steps until all tests pass.
  5. Check the solutions to see if there are other ways to solve. (Remember, the solution may be less performant than yours)
  6. Rinse and repeat (delete and checkout again, then back to Step 1) to build muscle memory.

Each test class has two types of test methods:

  • Solved test methods show how an invocation/access can be achieved with the traditional calls.

  • Unsolved/failing test methods provide TODO hints that will allow the kata-taker to manually solve the exercise to achieve the same with MethodHandles/VarHandles.

Mission

Your mission, should you choose to accept it, will be to fix the JUnit tests to achieve the same results with the Handles API as the solved one(s) do with traditional reflection. This message will self-destruct in NaN minutes

Requirements

How to prepare for coding along

This kata is developed as a Java maven project. Ensure that you have:

  1. Apache Maven 3.3.x or above. Tested with Apache Maven 3.5.0. Link: https://maven.apache.org/download.cgi

  2. JDK 11. Tested with OpenJDK 11 Link: http://jdk.java.net/11/

  3. Your favorite Java IDE. IntelliJ IDEA Ultimate was used to develop this kata.

Project Structure

The structure of the project:

|____pom.xml
|____README.md
|
|____src
| |
| |____test                    <------------------- Kata Tests
| | |____java
| |   |____none
| |     |____cvg
| |       |____constructors
| |       |____methods
| |       |____variables
| |
| |____main                    <------------------- Shared ErrorMessages & DemoClass
| | |____java
| |   |____none
| |     |____cvg
| |
| |____solutions               <------------------- Solutions 
| | |____java
| |   |____none
| |     |____cvg
| |       |____constructors
| |       |____methods
| |       |____variables

Java Reflection and recent alternates

There are a few JUnit tests with an aim to practice method access alternates to Reflection.

Tests Included

Constructor invocation

  1. DefaultConstructorInvocationTest.java

    This test aims at using MethodHandles to invoke a default constructor on a class in order to create a new instance.

  2. ParameteredConstructorInvocationTest.java

    This test aims at using MethodHandles to invoke a constructor with a parameter on a class in order to create a new instance.

Method invocation

  1. PublicMethodInvocationTest.java

    This test aims at using MethodHandles to invoke a public method on a class.

  2. PackageProtectedMethodInvocationTest.java

    This test aims at using MethodHandles to invoke a package-protected (default-access) method on a class.

  3. ProtectedMethodInvocationTest.java

    This test aims at using MethodHandles to invoke a protected method on a class.

  4. PrivateMethodInvocationTest.java

    This test aims at using MethodHandles to invoke a private method on a class.

  5. PublicStaticMethodInvocationTest.java

    This test aims at using MethodHandles to invoke a public static method on a class.

sun.misc.Unsafe and recent alternates

There are a few JUnit tests with an aim to practice variable access alternates to Unsafe.

Tests Included

  1. Get variable values

    GetterTest.java

    This test aims at showing the differences between traditional reflection/Unsafe usage and the Handles API.

    In each of the below: The traditional access test passes, solve the alternate.

    1. public variables.
    2. private variables.
    3. one-dimensional array variables.
    4. two-dimensional array variables.
  2. Compare and Set variable values

    CompareAndSet.java

    This test aims at showing the differences between traditional reflection/Unsafe usage and the Handles API.

    In each of the below: The traditional access test passes, solve the alternate.

    1. Using AtomicReference - Solved.
    2. Using AtomicReferenceFieldUpdater - Solved.
    3. Using Unsafe - Solved.
    4. Using VarHandle - Unsolved, use the TODOs to fix.
  3. Var Handles restrictions that were possible with Unsafe

    VarHandlesForbiddenUnsafeFeaturesTest.java

    This test aims at highlighting functionality available with Reflection/Unsafe that no longer are available using VarHandles.

    1. Modify a private final variable using traditional calls - Solved.
    2. Cannot modify a private final variable using VarHandles - Unsolved, use the TODOs to fix.
    3. Modify a public static final constant using traditional calls - Solved.
    4. Cannot modify a public static final constant using VarHandles - Unsolved, use the TODOs to fix.

Solutions

Solutions for each test:

Kata Test Solution
DefaultConstructorInvocationTest.java SDefaultConstructorInvocationTest.java
ParameteredConstructorInvocationTest.java SParameteredConstructorInvocationTest.java
---- ----
PublicMethodInvocationTest.java SPublicMethodInvocationTest.java
PackageProtectedMethodInvocationTest.java SPackageProtectedMethodInvocationTest.java
ProtectedMethodInvocationTest.java SProtectedMethodInvocationTest.java
PrivateMethodInvocationTest.java SPrivateMethodInvocationTest.java
PublicStaticMethodInvocationTest.java SPublicStaticMethodInvocationTest.java
---- ----
GetterTest.java SGetterTest.java
CompareAndSetTest.java SCompareAndSetTest.java
VarHandlesForbiddenUnsafeFeaturesTest.java SVarHandlesForbiddenUnsafeFeaturesTest.java

Take Away

The key take-away from this kata is a solid understanding of the simpler and more common usages of Core Reflection API and Unsafe API alongside the newer Handles API both in similarity and in certain cases, how they differ.

Who knows if your next open source/enterprise contribution is with helping out a library, framework or an enterprise application in converting to the newer APIs ?

You can’t perform that action at this time.