I recently started new project - a CPU emulator in Java.
Base code is written, now I can start to slowly implement new things, but I want code review to be done, to reformat code before it messes up.
Unfortunately, I didn't add any Javadocs and didn't do any deeper tests, except checking if basic OP codes are working.

https://github.com/jakub-gonet/Emulated-CPU

Code structure is like so: 

 - CommandHelper.py - script used to convert Op code to binary form and vice versa
 - Main - entry point
 - **cpu/OPCODE - list of OP codes and what they should do**
 - cpu/ADDR_TYPE - addressing modes
 - cpu/StatusFlags - CPU flags (carry, negative, zero flag etc)
 - cpu/programCounter - program counter
 - **cpu/CPUEmulator - main class to bind rest to it**
 - cpu/instructionArgument, InstructionMnemonic, Instruction - used to encode a single instruction
 - **cpu/instruction/InstructionRunner - fetch and run Instruction**
 - cpu/instruction/converter - package used to convert from bits to OP code and address modes
 - cpu/memory - package used to represent CPU memory

(bolded are important)

    package cpu.instruction;

    import cpu.ADDR_TYPE;
    import cpu.instruction.converter.ValueToAddressingMode;
    import cpu.instruction.converter.ValueToOPCode;
    import cpu.memory.Memory;

    public class InstructionRunner {
    public static void run(Instruction instruction) {
        if (instruction != null) {
            Integer arg2Value = (instruction.getArg2() != null) ? instruction.getArg2()
                                                                             .getValue() : null;

            Integer arg1Value = (instruction.getArg1() != null) ? instruction.getArg1()
                                                                             .getValue() : null;

            Integer address = (instruction.getArg1() != null) ? instruction.getArg1()
                                                                           .getAddress() : null;

            Integer value = instruction.getMnemonic()
                                       .getOpcode()
                                       .apply(arg1Value,
                                           arg2Value);

            if (instruction.getArgumentCount() > 0) instruction.getArg1()
                                                               .getMemory()
                                                               .write(address, value);
        } else throw new
            IllegalArgumentException("ERROR: Instruction can't be null.");

    }

    public static Instruction fetchInstruction(int address) {
        try {
            int opCodeAndAddresses = readFromMemory(address);
            InstructionMnemonic mnemonic = new InstructionMnemonic(
                ValueToOPCode.getOPCode(opCodeAndAddresses)
            );
            InstructionArgument[] arguments = createArguments(mnemonic.getRequiredArgs(), address, opCodeAndAddresses);

            return new Instruction(mnemonic, arguments[0], arguments[1]);

        } catch (IndexOutOfBoundsException e) {
            System.out.println("ERROR: OP code not recognized.");
        } catch (NullPointerException e) {
            System.out.println("ERROR: Bad format of instruction.");
        }
        return null;
    }

    private static InstructionArgument[] createArguments(int argumentCount, int address, int argumentsCode) {
        InstructionArgument arg2 = null;
        InstructionArgument arg1 = null;

        switch (argumentCount) {
            case 2:
                int arg2Code = readFromMemory(address + 2);
                ADDR_TYPE secondAddressType = getAddressType(2, argumentsCode);
                arg2 = new InstructionArgument(arg2Code, secondAddressType);
            case 1:
                int arg1Code = readFromMemory(address + 1);
                ADDR_TYPE firstAddressType = getAddressType(1, argumentsCode);
                arg1 = new InstructionArgument(arg1Code, firstAddressType);
        }
        return new InstructionArgument[] {arg1, arg2};
    }

    private static ADDR_TYPE getAddressType(int argumentNumber, int operatorAndAddressingModeCode) {
        if (argumentNumber == 1) return ValueToAddressingMode.getFirstArgAddressingMode(operatorAndAddressingModeCode);
        if (argumentNumber == 2) return ValueToAddressingMode.getSecondArgAddressingMode(operatorAndAddressingModeCode);
        throw new IllegalArgumentException("ERROR: OP code argument does not exist.");
    }

    private static int readFromMemory(int address) {
        return Memory.getInstance()
                     .read(address);
    }
    }

I mostly wonder if that null policy is good practice and how to manage exceptions in that type of project.