First, Java White Paper about bytecodes.

Java Infrastructure The Java Programming Language, Arnold and Gosling

Java is designed to maximize portability. Many details about Java are specifically defined for all implementations. For example, an int is a 32-bit two's complement signed integer. Many languages leave precise definitions to particular implementations, making only general guarantees such as minimum range, or provide a way to ask the system what range is on the current platform.

Java makes these definitions all the way down to the machine language into which Java code is translated. Java source code is compiled into Java bytecodes , designed to be run on a Java virtual machine. Bytecodes are a machine language for an abstract machine, but are interpreted by the virtual machine on each system that supports Java.

The virtual machine assigns each application its own runtime, which both isolates applications from each other and provides a security model. Each runtime's security manager decides on the capabilities available to the application. The security manager could, for example, forbid the application from reading and writing the local disk, or allow network connections only to particular machines.

These features combined give Java code complete platform independence to provide a security model suitable for executing code downloaded across the network at varying levels of trust. Java source code compiled into bytecodes can be run on any machine with a Java virtual machine. The code can be executed with an appropriate level of protection to prevent careless or malicious class writers from harming the system. the level of trust can be adjusted depending on the source of the bytecodes - bytecodes on the local disk or protected network can be trusted more than bytecodes fetched from arbitrary machines elsewhere in the world.

See Java in a Nutshell pages7 and 142 about bytecodes and security.

Also see Exploring Java about code verification,

The Byte Code Verification Process from the Java White Paper