Many profilers based on bytecode instrumentation yield wrong results in the presence of an optimizing dynamic compiler, either due to not being aware of optimizations such as stack allocation and method inlining, or due to the inserted code disrupting such optimizations. To avoid such perturbations, we present a novel technique to make any profiler implemented at the bytecode level aware of optimizations performed by the dynamic compiler. We implement our approach in a state-of-the-art Java VM and demonstrate its significance with three concrete profilers. Two of them allow us to quantify the impact of certain dynamic compiler optimizations on standard benchmarks. The third profiler is part of a new testing framework for locating performance bugs in dynamic compiler implementations.