The dreaded moment has come. You have made it this far, and now it is time to face the trial. The young man sitting before you has just finished scrawling out an infamous problem on the conference room whiteboard – a trial of iteration and divisibility. This would confound the rookie programmer, but you have a wealth of such victories under your belt.

There is just one problem.

You are a Java programmer by nature; it is the very air you breathe and caffeine you drink. But the age of Java has begun to wane, and your old employment is no more. You must do what you can to survive, and this means you must adapt. This is a Python shop.

You stare blankly at IDLE, taking in the strange orange keywords. A twinge of nostalgia for the off-purple of Eclipse hits you, but you are interrupted by the interviewer.

“Um, are you ready to get started?”

His tone is polite, but you must not let down your guard.

“Yes, yes…”

You reply, but do not take your eyes off the screen.

“Uh, don’t worry about this too much. We just want to get a sense for how you solve problems with Python.”

You take a deep, final breath. You are ready.

Your fingers trained well from years of writing classes and imports by hand, you quickly develop a suitable framework.

import sys

def main(args):
    pass

if __name__ == "__main__":
    args = sys.argv
    main(args)

You feel slightly comforted at the sight of your work. But it is short-lived, for now comes the difficult part.

Your father was a Java programmer, and imparted much wisdom to you before his retirement. He warned against the serpent’s classes. You recall one saying of his in particular:

“Should you find yourself stranded in a foreign land, carve out a home for yourself.”

You remember a familiar sequence of bytes.

0xca, 0xfe, 0xba, 0xbe  # magic

Your heart warms thinking of the youthful days spent poring over the Java Virtual Machine specification, but you must not dawdle. The interviewer is waiting, and you must deliver him nothing but the best.

“Now comes the version…” You mutter, typing away.

0x00, 0x00,  # minor
0x00, 0x31,  # major

Of course, no class is complete without constants. You reckon 24 ought to be enough for the job.

0x00, 0x19,             # constant_pool_count: 25 (24 constants)

“Now, let’s have some Strings and our class…” The interviewer appears somewhat concerned at your mumbling, but is nevertheless silent.

# CONSTANT POOL START
# 0x01
0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
0x46, 0x69, 0x7a, 0x7a, # "Fizz"
# 0x02
0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
0x42, 0x75, 0x7a, 0x7a, # "Buzz"
# 0x03
0x01, 0x00, 0x08,       # UTF-8 string, 8 chars
0x46, 0x69, 0x7a, 0x7a, # "Fizz"
0x42, 0x75, 0x7a, 0x7a, # "Buzz"
# 0x04
0x07, 0x00, 0x03,       # class "FizzBuzz"

“Ah, right. We’ll certainly need some code.”

# 0x05
0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
0x43, 0x6f, 0x64, 0x65, # "Code"

“And our dear friend System…”

# 0x06
0x01, 0x00, 0x10,       # UTF-8 string, 16 chars
0x6a, 0x61, 0x76, 0x61, # "java"
0x2f, 0x6c, 0x61, 0x6e, # "/lan"
0x67, 0x2f, 0x53, 0x79, # "g/Sy"
0x73, 0x74, 0x65, 0x6d, # "stem"
# 0x07
0x07, 0x00, 0x06,       # class "java/lang/System"

“… to get at the standard output, of course.” The bytes are coming naturally now. Like any respectable Java programmer, you know the class file format better than your own apartment.

# 0x08
0x01, 0x00, 0x03,       # UTF-8 string, 3 chars
0x6f, 0x75, 0x74,       # "out"
# 0x09
0x01, 0x00, 0x15,       # UTF-8 string, 21 chars
0x4c, 0x6a, 0x61, 0x76, # "Ljav"
0x61, 0x2f, 0x69, 0x6f, # "a/io"
0x2f, 0x50, 0x72, 0x69, # "/Pri"
0x6e, 0x74, 0x53, 0x74, # "ntSt"
0x72, 0x65, 0x61, 0x6d, # "ream"
0x3b,                   # ";"
# 0x0a
0x0c,                   # name and type
0x00, 0x08,             # name_index: 8 ("out")
0x00, 0x09,             # descriptor_index: 9 ("Ljava/io/PrintStream;")
# 0x0b
0x09,                   # field reference
0x00, 0x07,             # java/lang/System class
0x00, 0x0a,             # name and type index

“We’ll certainly need to print, so…”

# 0x0c
0x01, 0x00, 0x07,       # UTF-8 string, 7 chars
0x70, 0x72, 0x69, 0x6e, # "prin"
0x74, 0x6c, 0x6e,       # "tln"
# 0x0d
0x01, 0x00, 0x15,       # UTF-8 string, 21 chars
0x28, 0x4c, 0x6a, 0x61, # "(Lja"
0x76, 0x61, 0x2f, 0x6c, # "va/l"
0x61, 0x6e, 0x67, 0x2f, # "ang/"
0x53, 0x74, 0x72, 0x69, # "Stri"
0x6e, 0x67, 0x3b, 0x29, # "ng;)"
0x56,                   # "V"
# 0x0e
0x0c,                   # name and type
0x00, 0x0c,             # name_index: 12 ("println")
0x00, 0x0d,             # descriptor_index: 13 ("(Ljava/lang/String;)V")

“Ah, right. Can’t forget printing integers, too.”

# 0x0f
0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
0x28, 0x49, 0x29, 0x56, # "(I)V"
# 0x10
0x0c,                   # name and type
0x00, 0x0c,             # name_index: 12 ("println")
0x00, 0x0f,             # descriptor_index: 15 ("(I)V")
# 0x11
0x01, 0x00, 0x13,       # UTF-8 string, 19 chars
0x6A, 0x61, 0x76, 0x61, # "java"
0x2F, 0x69, 0x6F, 0x2F, # "/io/"
0x50, 0x72, 0x69, 0x6E, # "Prin"
0x74, 0x53, 0x74, 0x72, # "tStr"
0x65, 0x61, 0x6D,       # "eam"

Your fingers are moving at an alarming pace. You know your own limits, but the interviewer appears to be getting increasingly uneasy at the suprisingly loud noises coming from the laptop’s rubber-domed keyboard.

# 0x12
0x07, 0x00, 0x11,       # class "java/io/PrintStream"
# 0x13
0x0a,                   # method reference
0x00, 0x12,             # java/io/PrintStream class
0x00, 0x0e,             # name and type index
# 0x14
0x0a,                   # method reference
0x00, 0x12,             # java/io/PrintStream class
0x00, 0x10,             # name and type index

“Oh, almost forgot to wrap the Strings.”

# 0x15
0x08, 0x00, 0x01,       # String "Fizz"
# 0x16
0x08, 0x00, 0x02,       # String "Buzz"
# 0x17
0x08, 0x00, 0x03,       # String "FizzBuzz"

“And our method signature for the final touch…”

# 0x18
0x01, 0x00, 0x03,       # UTF-8 string, 3 chars
0x28, 0x29, 0x56,       # "()V"
# CONSTANT POOL END

Now comes a simple, well-known series of bytes, designed by Sun to give the programmer a little breather.

0x00, 0x01,             # access_flags: public
0x00, 0x04,             # this_class: "Fizz"
0x00, 0x12,             # super_class: "java/io/PrintStream"
0x00, 0x00,             # interfaces_count: 0
0x00, 0x00,             # fields_count: 0
0x00, 0x01,             # methods_count: 1

You smirk at the superclass trick – your father had taught you not to be wasteful, and that any inheritable class will usually do. A classic tactic for any handwritten class file.

It is now time to lay the groundwork for the problem at hand. You do not waver, for all that you should ever need lies available to you in the constant pool.

# METHODS START
# 0x00
0x00, 0x09,             # access_flags: public, static
0x00, 0x03,             # name_index: 3 ("FizzBuzz")
0x00, 0x18,             # descriptor_index: 24 ("()V")
0x00, 0x01,             # attributes_count: 1
# METHOD ATTRIBUTES START
# 0x00
0x00, 0x05,             # attribute_name_index: 5 ("Code")
0x00, 0x00, 0x00, 0x5c, # attribute_length: 12 + code_length
0x00, 0x02,             # max_stack: 2
0x00, 0x04,             # max_locals: 4
0x00, 0x00, 0x00, 0x50, # code_length: 80

You have already envisioned the instructions in entirety. You could do the jump offset calculations in your sleep. All that remains is a swift barrage of keystrokes.

# CODE START
0x03,                   # push 0 onto stack
0x3b,                   # store into var 0
0x11, 0x00, 0x64,       # push 100 onto stack
0x3c,                   # store into var 1

# loop header
0x84, 0x00, 0x01,       # increment var 0
0x1a,                   # push var 0 onto stack
0x1b,                   # push var 1 onto stack
0xa3, 0x00, 0x44,       # if var 0 > var 1, jump 68 bytes

# i mod 3
0x1a,                   # push var 0 onto stack
0x06,                   # push 3 onto stack
0x70,                   # push var 0 mod 3 onto stack
0x3d,                   # store result in var 2

# i mod 5 
0x1a,                   # push var 0 onto stack
0x08,                   # push 5 onto stack
0x70,                   # push var 0 mod 5 onto stack
0x3e,                   # store result in var 3

# FizzBuzz?
0x1c,                   # push var 2 onto stack
0x1d,                   # push var 3 onto stack
0x60,                   # add results
0x9a, 0x00, 0x0e,       # if result != 0, jump 14 bytes
0xb2, 0x00, 0x0b,       # push System.out onto stack
0x12, 0x17,             # push "FizzBuzz" onto stack
0xb6, 0x00, 0x13,       # call println(String)
0xa7, 0xff, 0xe2,       # jump 30 bytes backward

# Fizz?
0x1c,                   # push var 2 onto stack
0x9a, 0x00, 0x0e,       # if result != 0, jump 14 bytes
0xb2, 0x00, 0x0b,       # push System.out onto stack
0x12, 0x15,             # push "Fizz" onto stack
0xb6, 0x00, 0x13,       # call println(String)
0xa7, 0xff, 0xd3,       # jump 45 bytes backward

# Buzz?
0x1d,                   # push var 3 onto stack
0x9a, 0x00, 0x0e,       # if result != 0, jump 14 bytes
0xb2, 0x00, 0x0b,       # push System.out onto stack
0x12, 0x16,             # push "Buzz" onto stack
0xb6, 0x00, 0x13,       # call println(String)
0xa7, 0xff, 0xc4,       # jump 60 bytes backward

# None of the above!
0xb2, 0x00, 0x0b,       # push System.out onto stack
0x1a,                   # push var 0 onto stack
0xb6, 0x00, 0x14,       # call println(int)
0xa7, 0xff, 0xba,       # jump 70 bytes backward

0xb1,                   # return void
# CODE END

All great things, as section 4.1 of the Java Virtual Machine specification tells, must end with an attribute table definition.

0x00, 0x00,             # exception_table_length: 0
0x00, 0x00,             # attributes_count: 0
# METHOD ATTRIBUTES END
# METHODS END
0x00, 0x00              # attributes_count: 0

You rest for a moment, for the class is done. It has all the handwritten love and care that you wouldn’t get from javac.

Your colleagues told you Python lacks support for Java classes. But you need not worry, for the power of Sun extends to many lands.

import java.lang.ClassLoader
import java.lang.String
from jarray import array
from org.python.core.util import StringUtil
import sys

def main(args):
    cls = [
        0xca, 0xfe, 0xba, 0xbe, # magic
        0x00, 0x00,             # minor
        0x00, 0x31,             # major
        0x00, 0x19,             # constant_pool_count: 25 (24 constants)
        # CONSTANT POOL START
        # 0x01
        0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
        0x46, 0x69, 0x7a, 0x7a, # "Fizz"
        # 0x02
        0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
        0x42, 0x75, 0x7a, 0x7a, # "Buzz"
        # 0x03
        0x01, 0x00, 0x08,       # UTF-8 string, 8 chars
        0x46, 0x69, 0x7a, 0x7a, # "Fizz"
        0x42, 0x75, 0x7a, 0x7a, # "Buzz"
        # 0x04
        0x07, 0x00, 0x03,       # class "FizzBuzz"
        # 0x05
        0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
        0x43, 0x6f, 0x64, 0x65, # "Code"
        # 0x06
        0x01, 0x00, 0x10,       # UTF-8 string, 16 chars
        0x6a, 0x61, 0x76, 0x61, # "java"
        0x2f, 0x6c, 0x61, 0x6e, # "/lan"
        0x67, 0x2f, 0x53, 0x79, # "g/Sy"
        0x73, 0x74, 0x65, 0x6d, # "stem"
        # 0x07
        0x07, 0x00, 0x06,       # class "java/lang/System"
        # 0x08
        0x01, 0x00, 0x03,       # UTF-8 string, 3 chars
        0x6f, 0x75, 0x74,       # "out"
        # 0x09
        0x01, 0x00, 0x15,       # UTF-8 string, 21 chars
        0x4c, 0x6a, 0x61, 0x76, # "Ljav"
        0x61, 0x2f, 0x69, 0x6f, # "a/io"
        0x2f, 0x50, 0x72, 0x69, # "/Pri"
        0x6e, 0x74, 0x53, 0x74, # "ntSt"
        0x72, 0x65, 0x61, 0x6d, # "ream"
        0x3b,                   # ";"
        # 0x0a
        0x0c,                   # name and type
        0x00, 0x08,             # name_index: 8 ("out")
        0x00, 0x09,             # descriptor_index: 9 ("Ljava/io/PrintStream;")
        # 0x0b
        0x09,                   # field reference
        0x00, 0x07,             # java/lang/System class
        0x00, 0x0a,             # name and type index
        # 0x0c
        0x01, 0x00, 0x07,       # UTF-8 string, 7 chars
        0x70, 0x72, 0x69, 0x6e, # "prin"
        0x74, 0x6c, 0x6e,       # "tln"
        # 0x0d
        0x01, 0x00, 0x15,       # UTF-8 string, 21 chars
        0x28, 0x4c, 0x6a, 0x61, # "(Lja"
        0x76, 0x61, 0x2f, 0x6c, # "va/l"
        0x61, 0x6e, 0x67, 0x2f, # "ang/"
        0x53, 0x74, 0x72, 0x69, # "Stri"
        0x6e, 0x67, 0x3b, 0x29, # "ng;)"
        0x56,                   # "V"
        # 0x0e
        0x0c,                   # name and type
        0x00, 0x0c,             # name_index: 12 ("println")
        0x00, 0x0d,             # descriptor_index: 13 ("(Ljava/lang/String;)V")
        # 0x0f
        0x01, 0x00, 0x04,       # UTF-8 string, 4 chars
        0x28, 0x49, 0x29, 0x56, # "(I)V"
        # 0x10
        0x0c,                   # name and type
        0x00, 0x0c,             # name_index: 12 ("println")
        0x00, 0x0f,             # descriptor_index: 15 ("(I)V")
        # 0x11
        0x01, 0x00, 0x13,       # UTF-8 string, 19 chars
        0x6A, 0x61, 0x76, 0x61, # "java"
        0x2F, 0x69, 0x6F, 0x2F, # "/io/"
        0x50, 0x72, 0x69, 0x6E, # "Prin"
        0x74, 0x53, 0x74, 0x72, # "tStr"
        0x65, 0x61, 0x6D,       # "eam"
        # 0x12
        0x07, 0x00, 0x11,       # class "java/io/PrintStream"
        # 0x13
        0x0a,                   # method reference
        0x00, 0x12,             # java/io/PrintStream class
        0x00, 0x0e,             # name and type index
        # 0x14
        0x0a,                   # method reference
        0x00, 0x12,             # java/io/PrintStream class
        0x00, 0x10,             # name and type index
        # 0x15
        0x08, 0x00, 0x01,       # String "Fizz"
        # 0x16
        0x08, 0x00, 0x02,       # String "Buzz"
        # 0x17
        0x08, 0x00, 0x03,       # String "FizzBuzz"
        # 0x18
        0x01, 0x00, 0x03,       # UTF-8 string, 3 chars
        0x28, 0x29, 0x56,       # "()V"
        # CONSTANT POOL END
        0x00, 0x01,             # access_flags: public
        0x00, 0x04,             # this_class: "Fizz"
        0x00, 0x12,             # super_class: "java/io/PrintStream"
        0x00, 0x00,             # interfaces_count: 0
        0x00, 0x00,             # fields_count: 0
        0x00, 0x01,             # methods_count: 1
        # METHODS START
        # 0x00
        0x00, 0x09,             # access_flags: public, static
        0x00, 0x03,             # name_index: 3 ("FizzBuzz")
        0x00, 0x18,             # descriptor_index: 24 ("()V")
        0x00, 0x01,             # attributes_count: 1
        # METHOD ATTRIBUTES START
        # 0x00
        0x00, 0x05,             # attribute_name_index: 5 ("Code")
        0x00, 0x00, 0x00, 0x5c, # attribute_length: 12 + code_length
        0x00, 0x02,             # max_stack: 2
        0x00, 0x04,             # max_locals: 4
        0x00, 0x00, 0x00, 0x50, # code_length: 80
        # CODE START
        0x03,                   # push 0 onto stack
        0x3b,                   # store into var 0
        0x11, 0x00, 0x64,       # push 100 onto stack
        0x3c,                   # store into var 1

        # loop header
        0x84, 0x00, 0x01,       # increment var 0
        0x1a,                   # push var 0 onto stack
        0x1b,                   # push var 1 onto stack
        0xa3, 0x00, 0x44,       # if var 0 > var 1, jump 68 bytes

        # i mod 3
        0x1a,                   # push var 0 onto stack
        0x06,                   # push 3 onto stack
        0x70,                   # push var 0 mod 3 onto stack
        0x3d,                   # store result in var 2

        # i mod 5
        0x1a,                   # push var 0 onto stack
        0x08,                   # push 5 onto stack
        0x70,                   # push var 0 mod 5 onto stack
        0x3e,                   # store result in var 3

        # FizzBuzz?
        0x1c,                   # push var 2 onto stack
        0x1d,                   # push var 3 onto stack
        0x60,                   # add results
        0x9a, 0x00, 0x0e,       # if result != 0, jump 14 bytes
        0xb2, 0x00, 0x0b,       # push System.out onto stack
        0x12, 0x17,             # push "FizzBuzz" onto stack
        0xb6, 0x00, 0x13,       # call println(String)
        0xa7, 0xff, 0xe2,       # jump 30 bytes backward

        # Fizz?
        0x1c,                   # push var 2 onto stack
        0x9a, 0x00, 0x0e,       # if result != 0, jump 14 bytes
        0xb2, 0x00, 0x0b,       # push System.out onto stack
        0x12, 0x15,             # push "Fizz" onto stack
        0xb6, 0x00, 0x13,       # call println(String)
        0xa7, 0xff, 0xd3,       # jump 45 bytes backward

        # Buzz?
        0x1d,                   # push var 3 onto stack
        0x9a, 0x00, 0x0e,       # if result != 0, jump 14 bytes
        0xb2, 0x00, 0x0b,       # push System.out onto stack
        0x12, 0x16,             # push "Buzz" onto stack
        0xb6, 0x00, 0x13,       # call println(String)
        0xa7, 0xff, 0xc4,       # jump 60 bytes backward

        # None of the above!
        0xb2, 0x00, 0x0b,       # push System.out onto stack
        0x1a,                   # push var 0 onto stack
        0xb6, 0x00, 0x14,       # call println(int)
        0xa7, 0xff, 0xba,       # jump 70 bytes backward

        0xb1,                   # return void
        # CODE END
        0x00, 0x00,             # exception_table_length: 0
        0x00, 0x00,             # attributes_count: 0
        # METHOD ATTRIBUTES END
        # METHODS END
        0x00, 0x00              # attributes_count: 0
    ]

    c = StringUtil.toBytes(java.lang.String([chr(x) for x in cls]))

    class BCL(java.lang.ClassLoader):
        def load(self, name, bs):
            return self.super__defineClass(name, bs, 0, len(bs))

    BCL().load("FizzBuzz", c).getMethod("FizzBuzz").invoke(None)

if __name__ == "__main__":
    args = sys.argv
    main(args)

You mentally thank the good people of Jython, and turn your laptop towards the interviewer. Seeming to have been contemplating something a bit unpleasant, he snaps back to reality. He glances at the code on your screen.

“O-oh. Right, you’re finished?”

His eyes scan the lines from top to bottom. A look of deep unsettlement begins to show.

“What… what is all this for exactly?” He mutters under his breath, seeming to direct the question at himself rather than you.

“Just some standard Java interop. Using a custom classloader is more efficient here.”

You lean over and type a line into the console.

jython fizzbuzz.py

You are greeted back by a pleasant stream of data.

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
...

The interview does not continue long afterwards. The interviewer leaves the room and a different man comes to escort you out. They will be in touch.