Reputation: 39264
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
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