Bytecode is the set of instructions used by the JVM. To illustrate this let's take this Hello World program.
public static void main(String[] args){
System.out.println("Hello World");
}
This is what it turns into when compiled into bytecode.
public static main([Ljava/lang/String; args)V
getstatic java/lang/System out Ljava/io/PrintStream;
ldc "Hello World"
invokevirtual java/io/PrintStream print(Ljava/lang/String;)V
getstatic - Retreives the value of a static field of a class. In this case, the PrintStream "Out" of System.
ldc - Push a constant onto the stack. In this case, the String "Hello World"
invokevirtual - Invokes a method on a loaded reference on the stack and puts the result on the stack. Parameters of the method are also taken from the stack.
There are 255 opcodes, but not all of them are implemented yet. A table with all of the current opcodes can be found here: Java bytecode instruction listings.
There's multiple ways to write and edit bytecode. You can use a compiler, use a library, or use a program.
For writing:
For editing:
There's probably a specific documentation page specificially for bytecode. This page focuses on the modification of bytecode using different libraries and tools.