Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The queries were unusual in that the result set would contain a relatively large number of rows. This is not a good practice of course, but I only have a handful of these cases, for good reasons.
Of course one would expect the driver to use a server side cursor. It doesn't. There are ways of giving a JDBC driver hints about how to do the query. The driver I have ignores these and does whatever it feels like anyway. So the solution was to tell the MySQL driver in no uncertain terms, using driver specific settings, that the results would be scanned forward only, etc. so as to conserve memory.
PreparedStatement stmt;
...
stmt = conn.prepareStatement("select * from MyLargeTable", java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
ResultSet rs = stmt.executeQuery();
Problem solved.