John Humphreys
John Humphreys

Reputation: 39264

Can you break a Scala singleton (object)?

Coming from the Java world, one of the most popular programming texts is "Effective Java" by Joshua Bloch.

One of the many topics in that book instructs programmers to prefer enum-based singletons to standard singleton implementations because most standard implementations can be broken via serialization, cloning, etc.

My Question

Can the standard Scala singleton, which seems to be defined by using "object" rather than "class", can be broken via similar tricks? Or is it protected by the run-time environment much like an enum-based singleton is in Java?

Upvotes: 1

Views: 228

Answers (1)

Clashsoft
Clashsoft

Reputation: 11882

If you try hard enough, there is nothing that will stop you from copying any object, including enum values, in Java. However, since you cannot create an instance of an enum using 'normal' reflection, you have to go a little deeper in the hacker tool box: sun.misc.Unsafe. This is only used the create the instance, the rest can be done with normal reflection:

Unsafe unsafe = ...; // Obtain the value of the sun.misc.Unsafe.theUnsafe field, using normal reflection
    try
    {
        Object o = unsafe.allocateInstance(TestEnum.class); // creates a new instance of TestEnum with all fields set to 0 / false / null
        System.out.println(o); // prints 'null' because the name field is null
        System.out.println(o.getClass()); // prints 'JavaTest$Enum'

        Field f = Enum.class.getDeclaredField("name");
        f.setAccessible(true); // bypasses the final and access checks
        f.set(o, "TEST"); // set the name to 'TEST'
        f = Enum.class.getDeclaredField("ordinal");
        f.setAccessible(true);
        f.set(o, 1); // set the ordinal to 1

        System.out.println(o); // prints 'TEST'
        System.out.println(((Enum) o).ordinal()); // prints 1
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }

Additionally, you might want to copy the fields from the INSTANCE of TestEnum to your new instance of TestEnum. This can either be done manually as seen above (by messing with the parameters to f.set(o, ...) a bit) or by looping through all fields and copying them, like so:

for (Field f : TestEnum.class.getDeclaredFields())
{
    if (!Modifiers.isStatic(f.getModifiers())
    {
        f.setAccessible(true);
        f.set(o, f.get(TestEnum.INSTANCE));
    }
}

Of course this only copies the fields in the TestEnum class, which in my case has no fields. You might want to copy the fields in Enum as well, as they are not handled by this for loop.

To give a proper answer to your question: Yes you can break a Scala object as much as you can break an enum. It all depends on how much effort you are willing to take and how large your illegal code arsenal is.

Upvotes: 3

Related Questions