it depends on the bean scope - actually only beans with @Dependent pseudo-scope are problematic and cannot be properly destroyed, other built-in scopes should work (release is performed automatically once the bean is destroyed). For dependent beans you would have to store the CreationalContext and invoke bean.destroy(instance, creationalContext) manually.
I have done once, better not to do this way, you can call BeanManager.fireEvent() to let CDI do stuff instead of that. it's safer than this. also use VisualVM you should be able to tell if there is memory leak.