Tanto o Hibernate quanto o EclipseLink usam o padrão de design Proxy para implementar o carregamento lento / ansioso de relacionamentos de entidade. Os proxies são entrelaçados no bytecode do Java no momento da construção (estaticamente) ou no tempo de execução (dinamicamente) - basicamente aprimorando seus POJOs da Entidade. Outras características, como a verificação suja, também são tecidas no bytecode.
Esta é uma aplicação do Aspect Oriented Programming (AOP). Todas as mesmas armadilhas (por exemplo, classes inesperadas em tempo de execução) e vantagens (por exemplo, código-fonte mais limpo, injeção de código em tempo de execução) se aplicam.
Então a questão é: quais são as alternativas? Você pode desabilitar a tecelagem e implementar os mesmos recursos (carregamento lento, verificação suja, etc.) em seu próprio código - sem surpresas de tempo de execução, mas com maior esforço de desenvolvimento.
Como regra geral, use anotações, evite a inspeção de classe de entidade em tempo de execução e confie em tecelagem de código Hibernate ou Eclipselink para entregar o que você deseja. Observe que você sempre tem a opção de implementar seus próprios proxies, etc., se a complexidade exigir isso.