Java is one that comes in for a lot of hate from the web community. I think a big part of that comes from different concepts of what it means to have a "big team".
Scaling up applications is hard. Mostly, this is due to the need to maintain a coherent application architecture, while still minimising coupling between components.
The approach the dynamic languages tend to take to this problem is to use something other than ordinary calls between components that need to have low coupling, with a message or task queue of some kind being a very popular option.
Java is designed to allow a single code base to be scaled up, with the compartmentalisation enforced at the language level. However, this ability to handle high end complexity comes at a very high cost: the minimum level of complexity in Java is very high.
You certainly can't realistically use Java as a prototyping language, but as an implementation language, it's got a lot to recommend it.
However, I also believe that very restrictiveness is the cause of Java's culture of bundling patched versions of dependencies. The encapsulation enforcement is so effective that you really have no other choice if there's an error or missing feature in a dependency that you can't workaround. In the dynamic languages, you'll often have the option of creating a runtime fork via monkeypatching, so there's no need to actually patch the source code.