I would just use a simple integer counter and print it in base 3 :
for (int i=0; i < Math.pow(3, 20); i++) {
    System.out.println(Integer.toString(i, 20));
}
This is actually sufficient to represent your 20 variable object and generate all its states, however we have a lot of conversions to do to meet your requirements :
- the number would naturally use the 0,1and2symbols, we have to shift them to1,2and3
- the number wouldn't naturally be padded. We use the %1$20sformat descriptor, which means "positional argument 1, as a 20 char string (padded left by default)". That pads with spaces however, so we must also replace spaces with1.
Which gives us this final code :
for (int i=0; i < Math.pow(3, 20); i++) {
    System.out.println(String.format("%1$20s", Integer.toString(i, 20)).replace("2", "3").replace("1", "2").replace("0", "1").replace(" ", "1"));
}
Edit : why must I write ugly code when I can use streams and lambdas?
IntStream.range(0, (int)Math.pow(3, 20))                       // yields 0 to 3^20-1
         .mapToObj(number -> Integer.toString(number, 3))      // base 3 conversion
         .map(string -> String.format("%1$20s", string))       // 20 char padding
         .map(paddedString -> paddedString.replace("2", "3"))  // number shifting. must be made in this specific order not to fail
         .map(paddedString -> paddedString.replace("1", "2"))
         .map(paddedString -> paddedString.replace("0", "1"))
         .map(paddedString -> paddedString.replace(" ", "1"))
         .forEach(System.out::println);