Does the this reference escape during construction problem (as called by Brian Goetz and others in Java Concurrency in Practice) affect single-threaded programs or just multi-threaded programs? I mean, is it OK to let the this reference escape during construction if my classes aren't supposed to be thread-safe anyway?
EDIT: For example, here:
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
EDIT2: The motivation for my question is that the plugin WindowBuilder for Eclipse creates (or seems to create...) the action listeners in a JFrame's constructor and by default passing anonymous classes to those, thereby allowing the this reference to escape...
Generally speaking you shouldn't try to use your object until it is fully constructed. If you pass the object to some other code before it has been fully initialised this can lead to confusing results, unless you are very careful. Even in single threaded programs.
That said, sometimes it is not a problem esp if you know the object will not be used until later.
Allowing the "this" reference to escape isn't necessarily going to cause problems. It can work out okay, but it's completely dependent on what the other code does with it.
So why is it a best practice to not leak this in the constructor? What if EventSource were to send a "now connected" event immediately from within the register function. What happens? doSomething() gets called (and mind you, you're still mid-constructor and may not be done initializing the object). It entirely depends on what the method does, but one of the following is true:
everything you need in doSomething is initialized before the listener is registered, and things work out.
something is null, and you ignore it, leading to unexpected results
something blows up as a result of something being null when it shouldn't be (NPE or similar).
But, you say, it doesn't send that event. So you're okay, right? Well, until someone else changes it, and it starts sending something like that, and then you spontaneously break without a direct change to your code.
Short form: avoid doing that if you can; it can cause headaches. If you absolutely must for some reason, take care that you initialize everything that you can before leaking it, and take great care to understand what's going to happen, and realize that there's potential for future trouble.
Don't do it. Letting a reference escape before construction can cause unspecified behavior. Use the static factory pattern and let your worries rest, multiple threads or not
In your example it would look like this:
public class ThisEscape{
private final EventListener listener;
private ThisEscape(){
listener = new EventListener();
}
public static public ThisEscape makeEscape(EventSource source){
ThisEscape e = new ThisEscape();
source.registerListener(e.listener);
return e;
}
private class EventListener{
public void onEvent(Event e){
doSomething(e);
}
}
}
Obviously the static factory doesn't allow for seamless class extension, but in my experience this is not generally a problem, even if a few factory methods need to be made.
This code would be thread safe in regards to construction; be sure to mind that the rest of your class is thread safe.
Related
I have a class from an external API and I want to create an instance of it and access that object's methods from different threads. My questions are as comments in the following code:
import java.util.concurrent.Executors;
public class ThreadSafetyQuestion {
static class ExternalAPIObject {
void method(){
}
}
private static volatile ExternalAPIObject obj;
static synchronized ExternalAPIObject syncGetObject(){
return obj;
}
public static void main(String[] args) {
Executors.newSingleThreadExecutor().submit(()-> {
ThreadSafetyQuestion.syncGetObject().method();//Is this thread safe?
ExternalAPIObject externalAPIObject = ThreadSafetyQuestion.syncGetObject();
//do some other stuff
externalAPIObject.method();//I doubt this is thread safe. How can I access this method from multiple threads in a safe way?
});
}
}
You are looking at this from the wrong perspective. Thread safe means: when more than one thread invokes these methods nothing bad happens. It is really simple: when method() does manipulate "internal data" without any form of synchronisation - then having more than one thread call method() on the same object can result in a problem.
Thus: all the things that you put up in your question do not matter!
The only thing that matters: what exactly do these methods do that you are invoking?! In other words: there is no point in putting up a singleton to call methods in different threads. Or making the object reference volatile. All these ideas add zero in regards of making things "thread safe". Because you still allow method() to be called on the same object by different threads.
What you have to do instead: carefully check what exactly the methods you are invoking are doing.
And in case you don't want to go there: then create a single singleton that simply delegates calls to method() - but that has its methods marked as synchronized.
So: if you don't know anything about the external API - then one conservative approach is to make sure to always all its methods sequentially. Of course that can affect performance in very negative ways.
Long story short: it seems you are lacking basic understanding of multithreading concepts in Java. Don't go for trial/error then - rather step back and study this topic in depth! Seriously: multi-threading errors are subtle, they often go unnoticed for days or months. The first step in avoiding them: knowing what you are doing (instead of throwing some keywords at a problem that you somehow read about having this or that effect).
My Java is rusty-as-hell, and this threw me completely. I'm sure the answer is simple, but here's a simple example method that switches one Thingy off (if there's one already on) and another on:
private Thingy store;
public void switchiton(final Thingy pThingy) {
if (store != null)
store.endit();
pThingy.startit();
store = pThingy;
}
Problem: pThingy may be a subclass (e.g. CleverThingy) and not the superclass (Thingy), and CleverThingy overrides the endit method.
That code will always run the endit method in Thingy though - not the overridden one in CleverThingy (as it's declared as a Thingy and not a CleverThingy).
Obviously the method has no idea (and should not need one) about subclasses.
What am I missing that is staring at me in the face?
Update:
The subclass in this case is created "on the fly" (not sure of the correct term) rather than formally extended - e.g. in my Game class I have:
startthingy = new Thingy();
gamethingy = new Thingy() {
#Override
public void endit() {
// override things in here
super.endit();
}
}
switchiton(gamethingy); // DOES call gamethingy's overridden startit
switchiton(startthingy); // << gamethingy's overridden endit is NOT called!?
Simplest way to close this off is to answer it myself I think...
The commenters confirmed that how I thought it SHOULD work is how it actually should - this means the error is clearly elsewhere in the code...
I'm going to re-write all the anonymous classes to make them easier to debug and change a few of it's more dubious behaviours in the hope that tracks the error down
The core problem I asked - isn't really a problem tho, so...
Thanks for that!
I don't know if this is exactly the answer you are looking for (because it changes the Thingy class instead of the switchItOn() method), but I think I found a fairly easy and safe solution to your problem. If you are worried about someone extending Thingy and not properly doing whatever the endit() method needs to do, you could make it final. This will make it so that whatever is required to do in the endit() method will always be done and that method can't be overridden.
If you still want subclasses to be able to have flexability with that class, you could try something like this:
public class Thingy {
public void storeIt() {
//do stuff
}
public final void callEndIt() {
//do whatever stuff needs to be done every time in order for your program to work
endIt();
}
public void endIt() {
//this can be extended by subclasses safely
}
}
Then, you can just always call callEndIt() instead of endIt() so that whatever safety precautions you need to have done get fulfilled.
I'm sure you all know the behaviour I mean - code such as:
Thread thread = new Thread();
int activeCount = thread.activeCount();
provokes a compiler warning. Why isn't it an error?
EDIT:
To be clear: question has nothing to do with Threads. I realise Thread examples are often given when discussing this because of the potential to really mess things up with them. But really the problem is that such usage is always nonsense and you can't (competently) write such a call and mean it. Any example of this type of method call would be barmy. Here's another:
String hello = "hello";
String number123AsString = hello.valueOf(123);
Which makes it look as if each String instance comes with a "String valueOf(int i)" method.
Basically I believe the Java designers made a mistake when they designed the language, and it's too late to fix it due to the compatibility issues involved. Yes, it can lead to very misleading code. Yes, you should avoid it. Yes, you should make sure your IDE is configured to treat it as an error, IMO. Should you ever design a language yourself, bear it in mind as an example of the kind of thing to avoid :)
Just to respond to DJClayworth's point, here's what's allowed in C#:
public class Foo
{
public static void Bar()
{
}
}
public class Abc
{
public void Test()
{
// Static methods in the same class and base classes
// (and outer classes) are available, with no
// qualification
Def();
// Static methods in other classes are available via
// the class name
Foo.Bar();
Abc abc = new Abc();
// This would *not* be legal. It being legal has no benefit,
// and just allows misleading code
// abc.Def();
}
public static void Def()
{
}
}
Why do I think it's misleading? Because if I look at code someVariable.SomeMethod() I expect it to use the value of someVariable. If SomeMethod() is a static method, that expectation is invalid; the code is tricking me. How can that possibly be a good thing?
Bizarrely enough, Java won't let you use a potentially uninitialized variable to call a static method, despite the fact that the only information it's going to use is the declared type of the variable. It's an inconsistent and unhelpful mess. Why allow it?
EDIT: This edit is a response to Clayton's answer, which claims it allows inheritance for static methods. It doesn't. Static methods just aren't polymorphic. Here's a short but complete program to demonstrate that:
class Base
{
static void foo()
{
System.out.println("Base.foo()");
}
}
class Derived extends Base
{
static void foo()
{
System.out.println("Derived.foo()");
}
}
public class Test
{
public static void main(String[] args)
{
Base b = new Derived();
b.foo(); // Prints "Base.foo()"
b = null;
b.foo(); // Still prints "Base.foo()"
}
}
As you can see, the execution-time value of b is completely ignored.
Why should it be an error? The instance has access to all the static methods. The static methods can't change the state of the instance (trying to is a compile error).
The problem with the well-known example that you give is very specific to threads, not static method calls. It looks as though you're getting the activeCount() for the thread referred to by thread, but you're really getting the count for the calling thread. This is a logical error that you as a programmer are making. Issuing a warning is the appropriate thing for the compiler to do in this case. It's up to you to heed the warning and fix your code.
EDIT: I realize that the syntax of the language is what's allowing you to write misleading code, but remember that the compiler and its warnings are part of the language too. The language allows you to do something that the compiler considers dubious, but it gives you the warning to make sure you're aware that it could cause problems.
They cannot make it an error anymore, because of all the code that is already out there.
I am with you on that it should be an error.
Maybe there should be an option/profile for the compiler to upgrade some warnings to errors.
Update: When they introduced the assert keyword in 1.4, which has similar potential compatibility issues with old code, they made it available only if you explicitly set the source mode to "1.4". I suppose one could make a it an error in a new source mode "java 7". But I doubt they would do it, considering that all the hassle it would cause. As others have pointed out, it is not strictly necessary to prevent you from writing confusing code. And language changes to Java should be limited to the strictly necessary at this point.
Short answer - the language allows it, so its not an error.
The really important thing, from the compiler's perspective, is that it be able to resolve symbols. In the case of a static method, it needs to know what class to look in for it -- since it's not associated with any particular object. Java's designers obviously decided that since they could determine the class of an object, they could also resolve the class of any static method for that object from any instance of the object. They choose to allow this -- swayed, perhaps, by #TofuBeer's observation -- to give the programmer some convenience. Other language designers have made different choices. I probably would have fallen into the latter camp, but it's not that big of a deal to me. I probably would allow the usage that #TofuBeer mentions, but having allowed it my position on not allowing access from an instance variable is less tenable.
Likely for the same logical that makes this not an error:
public class X
{
public static void foo()
{
}
public void bar()
{
foo(); // no need to do X.foo();
}
}
It isn't an error because it's part of the spec, but you're obviously asking about the rationale, which we can all guess at.
My guess is that the source of this is actually to allow a method in a class to invoke a static method in the same class without the hassle. Since calling x() is legal (even without the self class name), calling this.x() should be legal as well, and therefore calling via any object was made legal as well.
This also helps encourage users to turn private functions into static if they don't change the state.
Besides, compilers generally try to avoid declaring errors when there is no way that this could lead to a direct error. Since a static method does not change the state or care about the invoking object, it does not cause an actual error (just confusion) to allow this. A warning suffices.
The purpose of the instance variable reference is only to supply the type which encloses the static. If you look at the byte code invoking a static via instance.staticMethod or EnclosingClass.staticMethod produces the same invoke static method bytecode. No reference to the instance appears.
The answer as too why it's in there, well it just is. As long as you use the class. and not via an instance you will help avoid confusion in the future.
Probably you can change it in your IDE (in Eclipse Preferences -> Java -> Compiler -> Errors/Warnings)
There's not option for it. In java (like many other lang.) you can have access to all static members of a class through its class name or instance object of that class. That would be up to you and your case and software solution which one you should use that gives you more readability.
It's pretty old topic but still up-to-date and surprisingly bringing higher impact nowadays. As Jon mentioned, it might be just a mistake Java's designers made at the very beginning. But I wouldn't imagine before it can have impact on security.
Many coders know Apache Velocity, flexible and powerful template engine. It's so powerful that it allows to feed template with a set of named objects - stricly considered as objects from programming language (Java originally). Those objects can be accessed from within template like in programming language so for example Java's String instance can be used with all its public fields, properties and methods
$input.isEmpty()
where input is a String, runs directly through JVM and returns true or false to Velocity parser's output). So far so good.
But in Java all objects inherit from Object so our end-users can also put this to the template
$input.getClass()
to get an instance of String Class.
And with this reference they can also call a static method forName(String) on this
$input.getClass().forName("java.io.FileDescriptor")
use any class name and use it to whatever web server's account can do (deface, steal DB content, inspect config files, ...)
This exploit is somehow (in specific context) described here: https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
It wouldn't be possible if calling static methods from reference to the instance of class was prohibited.
I'm not saying that a particular programming framework is better than the other one or so but I just want to put a comparison. There's a port of Apache Velocity for .NET. In C# it's not possible to call static methods just from instance's reference what makes exploit like this useless:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
I just consider this:
instanceVar.staticMethod();
to be shorthand for this:
instanceVar.getClass().staticMethod();
If you always had to do this:
SomeClass.staticMethod();
then you wouldn't be able to leverage inheritance for static methods.
That is, by calling the static method via the instance you don't need to know what concrete class the instance is at compile time, only that it implements staticMethod() somewhere along the inheritance chain.
EDIT: This answer is wrong. See comments for details.
Referring to my earlier question on incompletely constructed objects, I have a second question. As Jon Skeet pointed out, there's an implicit memory barrier in the end of a constructor that makes sure that final fields are visible to all threads. But what if a constructor calls another constructor; is there such a memory barrier in the end of each of them, or only in the end of the one that got called in the first place? That is, when the "wrong" solution is:
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
And the correct one would be a factory method version:
public class SafeListener {
private final EventListener listener;
private SafeListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
Would the following work too, or not?
public class MyListener {
private final EventListener listener;
private MyListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
}
public MyListener(EventSource source) {
this();
source.register(listener);
}
}
Update: The essential question is that is this() guaranteed to actually call the private constructor above (in which case there would be the barrier where intended and everything would be safe), or is it possible that the private constructor gets inlined into the public one as an optimization to save one memory barrier (in which case there wouldn't be a barrier until in the end of the public constructor)?
Are the rules of this() defined precisely somewhere? If not, then I think we must assume that inlining chained constructors is allowed, and probably some JVMs or maybe even javacs are doing it.
I think it is safe as java memory model states that:
Let o be an object, and c be a constructor for o in which a final
field f is written. A freeze action on final field f of o takes place
when c exits, either normally or abruptly. Note that if one
constructor invokes another constructor, and the invoked constructor
sets a final field, the freeze for the final field takes place at the
end of the invoked constructor.
An object is considered to be completely initialized when its constructor finishes.
This applies also for chained constructors.
If you have to register in the constructor define the listener as a static inner class. This is safe.
Your second version is not correct, because it is allowing the 'this' reference to escape from the construction process. Having 'this' escape invalidates the initialization safety guarantees that give final fields their safety.
To address the implicit question, the barrier at the end of construction only happens at the very end of object construction. The intuition one reader offered about inlining is a useful one; from the perspective of the Java Memory Model, method boundaries do not exist.
EDIT After the comment that suggested the compiler inlining the private constructor (I had not thought of that optimization) chances are that the code will be unsafe. And the worst part of unsafe multithreaded code is that is seems to work, so you are better off avoiding it completely. If you want to play different tricks (you do really want to avoid the factory for some reason) consider adding a wrapper to guarantee the coherence of data in the internal implementation object and register in the external object.
My guess is that it will be fragile but ok. The compiler cannot know whether the internal constructor will be called only from within other constructors or not, so it has to make sure that the result would be correct for code calling only the internal constructor, so whatever mechanism it uses (memory barrier?) has to be in place there.
I would guess that the compiler would add the memory barrier at the end of each and every constructor. The problem is still there: you are passing the this reference to other code (possibly other threads) before it is fully constructed --that is bad--, but if the only ´construction´ that is left is registering the listener, then the object state is as stable as it will ever be.
The solution is fragile in that some other day, you or some other programmer may need to add another member to the object and may forget that the chained constructors is a concurrency trick and may decide to initialize the field in the public constructor, and in doing so will add a hard to detect potential data race in your application, so I would try to avoid that construct.
BTW: The guessed safety may be wrong. I don't know how complex/smart the compiler is, and whether the memory barrier (or the like) is something it could try to optimize away... since the constructor is private the compiler does have enough information to know that it is only called from other constructors, and that is enough information to determine that the synchronization mechanism is not necessary in the internal constructor...
Escaping object reference in c-tor can publish an incompletely constructed object. This is true even if the publication is the last statement in the constructor.
Your SafeListener might not behave ok in a concurrent environment, even if c-tor inlining is performed (which I think it's not - think about creating objects using reflection by accessing private c-tor).
I'm sure you all know the behaviour I mean - code such as:
Thread thread = new Thread();
int activeCount = thread.activeCount();
provokes a compiler warning. Why isn't it an error?
EDIT:
To be clear: question has nothing to do with Threads. I realise Thread examples are often given when discussing this because of the potential to really mess things up with them. But really the problem is that such usage is always nonsense and you can't (competently) write such a call and mean it. Any example of this type of method call would be barmy. Here's another:
String hello = "hello";
String number123AsString = hello.valueOf(123);
Which makes it look as if each String instance comes with a "String valueOf(int i)" method.
Basically I believe the Java designers made a mistake when they designed the language, and it's too late to fix it due to the compatibility issues involved. Yes, it can lead to very misleading code. Yes, you should avoid it. Yes, you should make sure your IDE is configured to treat it as an error, IMO. Should you ever design a language yourself, bear it in mind as an example of the kind of thing to avoid :)
Just to respond to DJClayworth's point, here's what's allowed in C#:
public class Foo
{
public static void Bar()
{
}
}
public class Abc
{
public void Test()
{
// Static methods in the same class and base classes
// (and outer classes) are available, with no
// qualification
Def();
// Static methods in other classes are available via
// the class name
Foo.Bar();
Abc abc = new Abc();
// This would *not* be legal. It being legal has no benefit,
// and just allows misleading code
// abc.Def();
}
public static void Def()
{
}
}
Why do I think it's misleading? Because if I look at code someVariable.SomeMethod() I expect it to use the value of someVariable. If SomeMethod() is a static method, that expectation is invalid; the code is tricking me. How can that possibly be a good thing?
Bizarrely enough, Java won't let you use a potentially uninitialized variable to call a static method, despite the fact that the only information it's going to use is the declared type of the variable. It's an inconsistent and unhelpful mess. Why allow it?
EDIT: This edit is a response to Clayton's answer, which claims it allows inheritance for static methods. It doesn't. Static methods just aren't polymorphic. Here's a short but complete program to demonstrate that:
class Base
{
static void foo()
{
System.out.println("Base.foo()");
}
}
class Derived extends Base
{
static void foo()
{
System.out.println("Derived.foo()");
}
}
public class Test
{
public static void main(String[] args)
{
Base b = new Derived();
b.foo(); // Prints "Base.foo()"
b = null;
b.foo(); // Still prints "Base.foo()"
}
}
As you can see, the execution-time value of b is completely ignored.
Why should it be an error? The instance has access to all the static methods. The static methods can't change the state of the instance (trying to is a compile error).
The problem with the well-known example that you give is very specific to threads, not static method calls. It looks as though you're getting the activeCount() for the thread referred to by thread, but you're really getting the count for the calling thread. This is a logical error that you as a programmer are making. Issuing a warning is the appropriate thing for the compiler to do in this case. It's up to you to heed the warning and fix your code.
EDIT: I realize that the syntax of the language is what's allowing you to write misleading code, but remember that the compiler and its warnings are part of the language too. The language allows you to do something that the compiler considers dubious, but it gives you the warning to make sure you're aware that it could cause problems.
They cannot make it an error anymore, because of all the code that is already out there.
I am with you on that it should be an error.
Maybe there should be an option/profile for the compiler to upgrade some warnings to errors.
Update: When they introduced the assert keyword in 1.4, which has similar potential compatibility issues with old code, they made it available only if you explicitly set the source mode to "1.4". I suppose one could make a it an error in a new source mode "java 7". But I doubt they would do it, considering that all the hassle it would cause. As others have pointed out, it is not strictly necessary to prevent you from writing confusing code. And language changes to Java should be limited to the strictly necessary at this point.
Short answer - the language allows it, so its not an error.
The really important thing, from the compiler's perspective, is that it be able to resolve symbols. In the case of a static method, it needs to know what class to look in for it -- since it's not associated with any particular object. Java's designers obviously decided that since they could determine the class of an object, they could also resolve the class of any static method for that object from any instance of the object. They choose to allow this -- swayed, perhaps, by #TofuBeer's observation -- to give the programmer some convenience. Other language designers have made different choices. I probably would have fallen into the latter camp, but it's not that big of a deal to me. I probably would allow the usage that #TofuBeer mentions, but having allowed it my position on not allowing access from an instance variable is less tenable.
Likely for the same logical that makes this not an error:
public class X
{
public static void foo()
{
}
public void bar()
{
foo(); // no need to do X.foo();
}
}
It isn't an error because it's part of the spec, but you're obviously asking about the rationale, which we can all guess at.
My guess is that the source of this is actually to allow a method in a class to invoke a static method in the same class without the hassle. Since calling x() is legal (even without the self class name), calling this.x() should be legal as well, and therefore calling via any object was made legal as well.
This also helps encourage users to turn private functions into static if they don't change the state.
Besides, compilers generally try to avoid declaring errors when there is no way that this could lead to a direct error. Since a static method does not change the state or care about the invoking object, it does not cause an actual error (just confusion) to allow this. A warning suffices.
The purpose of the instance variable reference is only to supply the type which encloses the static. If you look at the byte code invoking a static via instance.staticMethod or EnclosingClass.staticMethod produces the same invoke static method bytecode. No reference to the instance appears.
The answer as too why it's in there, well it just is. As long as you use the class. and not via an instance you will help avoid confusion in the future.
Probably you can change it in your IDE (in Eclipse Preferences -> Java -> Compiler -> Errors/Warnings)
There's not option for it. In java (like many other lang.) you can have access to all static members of a class through its class name or instance object of that class. That would be up to you and your case and software solution which one you should use that gives you more readability.
It's pretty old topic but still up-to-date and surprisingly bringing higher impact nowadays. As Jon mentioned, it might be just a mistake Java's designers made at the very beginning. But I wouldn't imagine before it can have impact on security.
Many coders know Apache Velocity, flexible and powerful template engine. It's so powerful that it allows to feed template with a set of named objects - stricly considered as objects from programming language (Java originally). Those objects can be accessed from within template like in programming language so for example Java's String instance can be used with all its public fields, properties and methods
$input.isEmpty()
where input is a String, runs directly through JVM and returns true or false to Velocity parser's output). So far so good.
But in Java all objects inherit from Object so our end-users can also put this to the template
$input.getClass()
to get an instance of String Class.
And with this reference they can also call a static method forName(String) on this
$input.getClass().forName("java.io.FileDescriptor")
use any class name and use it to whatever web server's account can do (deface, steal DB content, inspect config files, ...)
This exploit is somehow (in specific context) described here: https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
It wouldn't be possible if calling static methods from reference to the instance of class was prohibited.
I'm not saying that a particular programming framework is better than the other one or so but I just want to put a comparison. There's a port of Apache Velocity for .NET. In C# it's not possible to call static methods just from instance's reference what makes exploit like this useless:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
I just consider this:
instanceVar.staticMethod();
to be shorthand for this:
instanceVar.getClass().staticMethod();
If you always had to do this:
SomeClass.staticMethod();
then you wouldn't be able to leverage inheritance for static methods.
That is, by calling the static method via the instance you don't need to know what concrete class the instance is at compile time, only that it implements staticMethod() somewhere along the inheritance chain.
EDIT: This answer is wrong. See comments for details.