The first problem is that you operate on only two Arraylists. Both exist on the heap and not - like you may think - on the stack of the recursive calls. So after the the first three calls the remaining is empty and in the first loop remaining.size() returns zero and the loop ends. So you must create two new arraylist with a copy constructor.
But even if you do so, the second problem is that you remove an object of your remaining while iterating over it. Your loop doesnt work correctly so. Try it with a java-for-each and you will raise an exception because it's not allowed.
Maybe you try it in a way like this:
public static void main(String[] args) {
Set<String> set = new HashSet<>(keys);
printPerm(new ArrayList<String>(), set);
}
static <T> void printPerm(List<T> stack, Set<T> rest) {
if (rest.isEmpty())
System.out.println(stack);
else
for (T element : rest) {
stack.add(element);
Set<T> restCopy = new HashSet<>(rest);
restCopy.remove(element);
printPerm(stack, restCopy);
stack.remove(element);
}
}