Locating the largest Collatz Sequence with memoization
Heap size


  The idea was to cache the sequence lengths for as many sequences as possible, from 0 to some value. I managed to (on my PC) get that value up to 1427500000, which is a large number.


When I try it with the same value, I run out of heap space.  That may be fixable by changing my JVM settings.  

Optimizing by combining steps


                    if (currentNumber % 2 == 0) {
                        currentNumber = currentNumber / 2;
                    } else {
                        currentNumber = 3 * currentNumber + 1;
                    }
                    chainSize++;



You say that you found that it was faster if you divided by 2 in the else as well, but it gives inaccurate chainSize values.  Have you considered 

                    if (currentNumber % 2 == 0) {
                        currentNumber /= 2;
                        chainSize++;
                    } else {
                        currentNumber = (3 * currentNumber + 1) / 2;
                        chainSize += 2;
                    }


This should give an accurate chainSize value if I'm understanding the optimization properly.  

Also, this uses the briefer /= notation where i /= 2; has the same value as i = i / 2;.  

Or 

                    if (currentNumber % 2 != 0) {
                        currentNumber = 3 * currentNumber + 1;
                        chainSize++;
                    }

                    currentNumber /= 2;
                    chainSize++;


I'll leave it up to you if these help with run time as well.  

Don't do useless checks

You have 


                if (currentNumber &gt; largestNumberAnyChain) {
                    largestNumberAnyChain = currentNumber;
                }



separate from the currentNumber update.  However, in two of the three branches, you reduce the value of currentNumber.  

Consider what happens if you move it into the previous code.  

                    if (currentNumber % 2 != 0) {
                        currentNumber = 3 * currentNumber + 1;
                        chainSize++;

                        if (currentNumber &gt; largestNumberAnyChain) {
                            largestNumberAnyChain = currentNumber;
                        }
                    }

                    currentNumber /= 2;
                    chainSize++;


This is the only branch where currentNumber increases, so it's the only one that needs checked.  

You could also move the check for negative numbers here for the same reason.  Note further that the largest check and the negative check will never be true at the same time.  

Avoid timing output


                System.out.println("New best: " + maxNumber + " at " + maxLength + " chains in " + ((double)(System.nanoTime() - startTime) / 1000000000) + "s.");
            }

            if (i % (maxTestValue / 100) == 0) {
                System.out.println("At " + i + " of " + maxTestValue + " (" + (i / (maxTestValue / 100)) + "%) in " + ((double)(System.nanoTime() - startTime) / 1000000000) + "s");
            }
        }

        System.out.println("Best: " + maxNumber + " at " + maxLength + " chains.");
        System.out.println("Largest number in any chain: " + largestNumberAnyChain);
        System.out.println("Took: " + ((double)(System.nanoTime() - startTime) / 1000000000) + " seconds.");



If you write this instead as 

            }
        }

        double elapsed = (double)(System.nanoTime() - startTime) / 1000000000;
        System.out.println("Best: " + maxNumber + " at " + maxLength + " chains.");
        System.out.println("Largest number in any chain: " + largestNumberAnyChain);
        System.out.println("Took: " + elapsed + " seconds.");


You might find that it runs faster.  

Same problem with 


                        System.out.println("Value from chain " + i + " at length " + chainSize + " is negative: " + currentNumber);



Measuring the time it takes to do the output distorts the overall timing.  It may not matter here, but it can be a bad habit to develop.