The problem with @PaulWagland solution is that almost all the encoders will do the allocation for the encoded byte array (or variants) for you. That is they are not garbage free.
I don't really recommend the following unless you know what you are doing.
Ideally what you want to do is have a massive byte[] set to the maximum size you expect and then reuse this byte[] either with a threadlocal or some sort of pooling.
Unfortunately Base64.java has the method you want hidden:
private int decode0(byte[] src, int sp, int sl, byte[] dst) {
...
}
(I'm not going to paste the code from the JDK but I'm sure you can easily find it).
Thus if you really want to go fast you would use that method on cached byte[] arrays.
Ideally though you would want to rewrite it to use ByteBuffers.
Alternatively as a stop gap you could use Base64.Decode#wrap but the problem with that method is that it will create a wrapping InputStream which is probably better than allocating new arrays but still not garbage free. You will also need to wrap your ByteBuffer/byte[] array in its own InputStream.
IMO its flaw that the Base64 encoder/decoder doesn't have what the CharsetEncoder has which is:
CharsetEncoder.encode(CharBuffer in, ByteBuffer out, boolean endOfInput)