How multithreading behaves in case of static members? Like in case of Singleton Class, if I try to create instance in a static block and in the static method, I return the instance and two threads try to execute getInstance() at the same time..how will this behave internally as static are loaded only one time
public class SingleTonUsingStaticInitialization {
private static SingleTonUsingStaticInitialization INSTANCE = null;
static {
try {
INSTANCE = new SingleTonUsingStaticInitialization();
} catch (Exception e) {
e.printStackTrace();
}
}
private SingleTonUsingStaticInitialization() {
}
public static SingleTonUsingStaticInitialization getInstance() {
return INSTANCE;
}
}
This specific example?
Threadingwise it's fine. Style wise it's deplorable. Do NOT write catch blocks like that. It also means if an exception does occur (it can't here - your constructor is empty), your code will dump half of the info to system error, and then continue, with a null reference instance of an instance of Singleton - causing other code to spit out NullPointerExceptions (because code just keeps going, as you caught the exception instead of letting it happen). If you treat all exceptions in this fashion, a single error will cause hundreds of errors in your logs, all irrelevant except the first one.
Once you take care of this exception handling issue, you can make the variable final, and no longer assign null to it. While you're at it, make the whole class final. It effectively is already (as you only have a private constructor):
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Single() {}
public static Singleton getInstance() {
return INSTANCE;
}
The reason this works out when 2 threads simultaneously invoke getInstance, is the classloader mechanism itself: The Classloader guarantees that any given class is never loaded more than once by the same loader, even if 2 threads would simultaneously require this (the classloader will synchronize/lock to avoid this situation), and the initialization process (the static block - which was needlessly convoluted, as the example above shows) is similarly guarded and cannot possibly occur twice.
That's the only freebie you get: For static methods as a general rule, all threads can just run the same method all simultaneously if they want to. And here they do - it's just that the initialization (which includes the ... = new Singleton(); part) is gated to occur only once.
NB: If you must do more complex things, make helper methods:
public final class Singleton {
private static Singleton INSTANCE = create();
private Singleton(Data d) {
// do stuff with 'd'
}
private static Singleton create() {
Data d;
try {
d = readStuffFromDataIncludedInMyJar();
} catch (IOException e) {
throw new Error("states.txt is corrupted", e);
}
return new Singleton(d);
}
}
This:
Keeps code simple - static initializers are a thing, but fairly exotic java.
Makes your code easier to test.
It's an internal file; if that is missing/broken, that's about as likely / as problematic as one of your class files having gone for a walk. An Error is warranted here. This cannot possibly occur unless you wrote a bug or messed up a build, and hard crashing with a clear exception telling you precisely what's wrong is exactly what you want to happen in that case, not for code to blindly continue in a state where half of your app is overwritten with gobbledygook due to a disk drive crash or what not. Best to just conclude everything's borked, say so, and stop running.
You are safe, in the sense that getInstance will return the same instance to multiple threads. This is guaranteed by The JLS, which is the only place you should delegate your understanding to. Specifically, that chapter says:
For each class or interface C, there is a unique initialization lock LC
And goes on further to say that:
The procedure for initializing C is then as follows:
Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC
In plain english, only a single thread can initialize that static field. Period.
The release of that lock gives proper happens-before guarantees between the action in the static block and any thread that uses that static field. This is implied from the same chapter, from:
An implementation may optimize this procedure by eliding the lock acquisition in step 1 (and release in step 4/5) when it can determine that the initialization of the class has already completed, provided that, in terms of the memory model, all happens-before orderings that would exist if the lock were acquired, still exist when the optimization is performed
Or, again, in plain english, whatever happens in that static block will be visible to all reading threads.
To that end, you will have a proper tool to remove that static block, via a so called "constant dynamic". The infrastructure for it is already in place, but javac still does not use it. You can read more here about it. Some projects already use that - if you have the proper jdk, for example jacoco does it.
See the fine points made in the Answer by rzwitserloot.
Here is similar code to the code seen there, but adapted to use an enum as your singleton. Many folks recommended an enum as the ideal way to define a singleton in Java.
Thread-safety is guaranteed because of the same class loader behavior discussed in the other Answer. The enum is loaded once, and only once, per class loader when the class first loads.
If you have multiple threads accessing the single object defined by this enum, the first thread to reach the point where this class is loaded will cause our enum object to be instantiated with its constructor method running. The other remaining threads will block on their attempt to access the enum object until the enum class finishes loading and its one and only named enum object finishes its construction. The JVM juggles all this contention automatically, with no further coding needed by us. All that behavior is guaranteed by the Java specifications.
package org.vaadin.example;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public enum AppContext
{
INSTANCE;
private String wording;
AppContext ( )
{
try
{
readStuffFromDataIncludedInMyJar();
}
catch ( IOException e )
{
throw new Error( "Failed to load from text file. Message # 7a608ddf-8c5f-4f77-a9c9-5ab852fde5b1." , e );
}
}
private void readStuffFromDataIncludedInMyJar ( ) throws IOException
{
Path path = Paths.get( "/Users/basilbourque/example.txt" );
String read = Files.readAllLines( path ).get( 0 );
this.wording = read;
System.out.println( "read = " + read );
}
public static void main ( String[] args )
{
System.out.println( AppContext.INSTANCE.toString() );
}
}
When run.
read = Wazzup?
INSTANCE
Related
I was asked this question in an interview.
There is a class, lets call it A. It has a default constructor and it initializes 2 different connections in its constructor.
Methods initDB & initSocket creates a DB connection and a socket connection and saves them in an instance field. They are just an example. They could also be file open or anything else.
Lets say a client instantiates an instance of this class. Now initDB executed successfully, but initSocket threw exception. So the object creation was aborted. But the DB connection was not closed prior to the exception. This resulted in a resource leak. How would I tackle this kind of resource leak?
E.g.
class A {
public A(){
this.dbConnection = initDB();
this.socketConnection = initSocket(); // throws exception
}
}
My initial answer was that I would not initialize these in constructor but in a separate init(). He countered by suggesting that this could be a legacy class, and I have been asked to maintain this. In which case I need to somehow clear the resource leak. How would I approach this problem?
I got stumped because instance creation threw an exception I lost any kind of reference to those connection fields. So I cannot call close() on them. But they will still be present in the OS level (this is my guess).
Note 1
As stated by Interviewer, I cannot change the behavior of the already written constructor. I can extend or do something around it, but cannot change the code.
Note 2
I think interviewer was not looking for explicitly any code that would handle this scenario. Would any JMX stuff help? I took a jibe at it & then we moved on. For those who think this is a very good question, I think interviewer knew this is not a general practice and probably would not be able to answer.
We have a few options here...
Box the thing off somewhere else. It's clearly problematic legacy code. Perhaps this "blob" which has access control issues can be moved into something some other process that can communicate with the rest of the system via RPC. You are better off doing this if the system is horribly broken. You can extend it other ways, such as composition; but if it's so sealed off you can't get it it, then you're boned
Use byte code modification. You could do this and you could get enough leverage to get what you need. ByteBuddy would come in handy for this. I wouldn't do this personally but hey, sometimes desperate measures call for desperate solutions...
If you can influence initDB, then you can decorate the return value with something else. For example, let's supposed it was some from some base class we did control or some other method we controlled, then we could perhaps do something like this
Connection initDb() {
try {
this.wrappedProvider.initDb();
} catch(Exception e) {
// .. destroy the connection...
}
}
... and then since you can influence this, you can change the effective semantics of it.
Can you influence the "Connection" of "A"? How does it get "A"? If it gets it from some DI container or something you can influence, then you can sub out the implementation for that class for something that "times out" if not talked to or initialized in some given time. Hacky, sure but without more info that's the best we're going to get...
Solution 1:
Provided that:
You can extend class A, and then use instances of class B instead,
method initSocket is overridable (not final nor private)
field dbConnection is accessible from class B (not private)
You can override method initSocket to close the dbConnection in case of an exception:
#Override
protected Socket initSocket() {
boolean ok = false;
try {
Socket result = super.initSocket();
ok = true;
return result;
} finally {
if (!ok) {
dbConnection.close();
}
}
}
Solution 2:
Provided that:
You can extend class A
method initDb is overridable (not final nor private)
You can wrap your A object in another class, and save the connection so that it can be closed in case of an exception:
class B {
private static ThreadLocal<Connection> CONNECTION = new ThreadLocal<>();
private final A delegate;
public B() {
boolean ok = false;
try {
delegate = new A() {
#Override
protected Connection initDb() {
Connection result = super.initDb();
CONNECTION.set(result);
return result;
}
};
ok = true;
} finally {
if (!ok) {
Connection cnt = CONNECTION.get();
if (cnt != null) {
cnt.close();
}
}
CONNECTION.set(null);
}
}
}
I have a peculiar requirement where I need ensure that only a particular method from one class is allowed to call a public (non-static) method from a second class. Inheritance cannot be used.
One option is to use StackTrace as follows:
ClassA.java
package org.rnd.stack;
public class ClassA {
public void methodA() throws IllegalAccessException {
Exception fake = new Exception("FAKE-IGNORE");
StackTraceElement[] stack = fake.getStackTrace();
StackTraceElement st = stack[1];
if ("org.rnd.stack.ClassB".equals(st.getClassName())
&& "methodB".equals(st.getMethodName())) {
System.out.println("You are allowed to call");
} else {
throw new IllegalAccessException("You are not allowed to call");
}
}
}
ClassB.java
package org.rnd.stack;
public class ClassB {
public void methodB() throws IllegalAccessException {
new ClassA().methodA();
}
public void illegalMethod() throws IllegalAccessException {
new ClassA().methodA();
}
public static void main(String[] args) {
try {
new ClassB().methodB();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Now the above solution works fine, but due to quality control in code audit I need to come up with another (or rather) better solution. Is there a better way to achieve this?
The right thing to do would be to revisit your requirement. A method that can only be called by certain other code paths is not compatible with public. The general best practice is to use package-private to prevent external callers, and accept that any code in the package could call the method, but won't because you or your team is auditing it.
Method visibility is ultimately not a secure solution to preventing execution; someone has your .class files and the ability to execute them on a machine, they can do just about anything they want. You shouldn't spend too much time trying to lock down method calls. Instead, document the intent of the method clearly (e.g. "Helper function for methodB(), please do not use elsewhere.") and trust the people developing with you know what they're doing. You can even give the method a clear name, like dangerousMethodBForInternalUseOnly() if you really want to beat people over the head about it.
You may also be interested in dependency-injection, which is a design pattern that uses the type system to protect (not prevent) people from executing dangerous code. Here's a couple of talks on Guice, a popular DI framework, that goes into more detail about the concept:
Google I/O 2009 - Big Modular Java with Guice
Java on Guice: Dependency Injection, the Java Way
All of that said, as an academic exercise here's one option for restricting method invocation to a fixed number of codepaths - rely on a shared secret. Add an Object secret field to your locked-down method, and cause the method to fail if the passed secret does not match a hard-coded value (private static final Object SECRET = new Object()). You can then use other mechanisms to share the secret only to code paths you allow (e.g. have a static initializer in your locked-down class publish it to classes you explicitly trust).
Obviously this can still be worked-around by a malicious developer, and it's pretty gross, but it would provide some sort of locking behavior assuming you can trust your locked-down class won't be changed without your knowledge.
A way to improve you method is that you don't need to create an exception to get the stacktrace, you can use the thread methods.
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Also maybe you want to use the class instead of handwriting the package. For example:
if (ClassB.class.getName().equals(st.getClassName())
&& "methodB".equals(st.getMethodName())) {
System.out.println("You are allowed to call");
} else {
throw new IllegalAccessException("You are not allowed to call");
}
Apart from that I don't know how you can do it better without changing your logic or using inheritance.
Pass caller as an argument and check if the caller is instanceof required class - multithreaded solution, cannot bypass by reflecion.
Get thread stack dump and check top entry - weird, heavy but possible
Create proxy - but that will be overheaded variation of solution 1.
You may be able to satisfy this requirement by using the class Class method getEnclosingMethod(). This is how it works (docs here):
If this Class object represents a local or anonymous class within a method, returns a Method object representing the immediately enclosing method of the underlying class.
The signature for methodA() should be changed to accept a Class object as parameter.
public void methodA(Class c) { }
The legal method from ClassB should create an anonymous class object, and pass its class as argument to methodA().
public void methodB() throws IllegalAccessException, NoSuchMethodException {
new ClassA().methodA(new Object(){}.getClass());
}
Then methodA() should check if the class enclosing method is indeed methodB() from ClassB.
public void methodA(Class c) throws IllegalAccessException, NoSuchMethodException {
if (c.getEnclosingMethod().equals(ClassB.class.getMethod("methodB"))) {
System.out.println("You are allowed to call");
} else {
throw new IllegalAccessException("You are not allowed to call");
}
}
Disadvantages:
You must instantiate a new object every time you call methodB(). This may get expensive depending on how many times you do it. Instead, you could create a local class inside methodB() so there is no object creation overhead:
public void methodB() throws IllegalAccessException, NoSuchMethodException {
class Local {};
new ClassA().methodA(Local.class);
}
You need to handle NoSuchMethodException and change the code if methodB() name changes;
Someone with access to the code could still modify methodB() to return the anonymous object class to another method, and use it to call methodA() from there. So this is not a perfect solution, but may be enough for your use case.
I'm writing a taglet-based library, which, when the first taglet is found, loads some configuration (starting with a text-file filled with properties).
The configuration object is being held statically directly in each Taglet object, but it seems that they are being garbage collected and then respawned by javadoc.exe in a subsequent taglet, causing the configuration to be reloaded over and over again.
Am I understanding this correctly, and is there a way around it? How can I make it so that configuration loads only once?
Thanks.
UPDATE
As mentioned in the comments, no, this does not impact performance or correctness. Since javadoc.exe is used by a single person on a single machine, performance is not much of an issue.
However, it clutters up the log each time configuration is loaded (at least five times per javadoc.exe run), and it does some moderately-heavy stuff, including loading package-lists from multiple websites, loading and parsing template files, and a bunch of other file processing. If there is any way to prevent this from happening many times in a single JavaDoc run, I would like to.
I have no experience with multithreading, so I may have this completely wrong...but what about setting up a daemon thread that does nothing but load configuration and then hold it all statically? This answer suggests that an I/O-based daemon thread is a bad idea, but I think it means ones that do ongoing I/O.
(I'm not sure if this would be something that should be manually started and stopped, or if its possible for the process itself to start the daemon thread... I'm going to read the concurrency chapters in Bloch's Effective Java...)
If two classes loaded by different ClassLoaders without parent-child relationship have to share data, the normal Java language constructs do not work. If you can get hands on a Class object or an instance, you have to access them via Reflection, even if it is the same class just loaded by different loaders.
Further, passing the data via heap variables won’t work as both ClassLoaders establish their own “namespace” hence a class loaded by two different loader creating two distinct Class objects will have their distinct copies of static variables as well. You need a storage which is independent from your own classes.
Thankfully, that storage exists in the context of Taglets. The register method receives a Map containing all previously registered Taglets. But besides the fact that you have to use Reflection rather than instanceof or Class comparison to find your “friend” Taglets, there is another obstacle: the JavaDoc implementation will wrap your Taglets within another object.
Putting it all together, you could implement the find-and-share logic into a base class of your Taglets and let the register method of the Taglets call it:
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;
public abstract class Base
{
static Properties CONFIG=new Properties();
static void initProperties(Map<?, ?> fromTagManager) {
String className=Base.class.getName();
for(Object o: fromTagManager.values()) {
o=extractTagLet(o);
if(o==null) continue;
for(Class<?> cl=o.getClass(); cl!=null; cl=cl.getSuperclass())
if(cl.getName().equals(className) && initFromPrevious(cl)) return;
}
// not found, first initialization
try {
CONFIG.load(Base.class.getResourceAsStream("config.properties"));
} catch(IOException ex) {
throw new ExceptionInInitializerError(ex);
}
}
private static Object extractTagLet(Object o) {
if(!o.getClass().getSimpleName().equals("LegacyTaglet"))
return o;
try {
Field f=o.getClass().getDeclaredField("legacyTaglet");
f.setAccessible(true);
return f.get(o);
} catch(NoSuchFieldException | IllegalAccessException ex) {
ex.printStackTrace();
}
return null;
}
private static boolean initFromPrevious(Class<?> cl) {
// this is the same class but loaded via a different ClassLoader
try {
Field f=cl.getDeclaredField("CONFIG");
f.setAccessible(true);
CONFIG=(Properties)f.get(null);
return true;
} catch(NoSuchFieldException | IllegalAccessException ex) {
return false;
}
}
}
Then a Taglet will be implemented like this:
import java.util.Map;
import com.sun.javadoc.Tag;
import com.sun.tools.doclets.Taglet;
public class ExampleTaglet extends Base implements Taglet {
#SuppressWarnings("unchecked")
public static void register(#SuppressWarnings("rawtypes") Map map) {
initProperties(map);
final ExampleTaglet taglet = new ExampleTaglet();
final String name = taglet.getName();
map.remove(name);// must ensure new Taglet is the last one (LinkedHashMap)
map.put(name, taglet);
}
// implement the Taglet interface below…
I have a singleton class in my play app. This singleton class is a long process which will generate reports from DB which consumes huge amount of memory. When i run my application in dev mode this singleton functionality is executing several times. I want this functionality to run only once. What should I do for that?
My code is:
public class DataGridManagerImpl extends ComponentContainer implements DataGridManager {
private static DataGridManager instance = null;
private DataGridManagerImpl(){
load();
}}
#Override
public void load() {
//Myreports function
}
public static DataGridManager getInstance(){
if (instance == null){
instance = new DataGridServiceManagerImpl();
}
return instance;
}
}
In my controller file inside a template function
DataGridManager dataGridMgr = DataGridManagerImpl.getInstance();
If i access the page it is executing the load reports function again.
Without code explaining how did you create your class it's hard to answer. From what I understand what you want is to run a process only once.
Problably the best approach is to use a Scheduled Job. This will trigger the process at a certain time, and Play ensures that only 1 instance of this process is running at the same time, even if the schedule would indicate another instance has to run. Let's say you have a process scheduled every hour and the process takes 3 hours. The initial process will be the only one running for 3 hours until it finishes.
Now, I would assume you want your process to be recurring as it generate reports. If not, if you only want to run it once, then you may want to use an asynchronous bootstrap job instead. This would run just once, at the beginning of the application.
EDIT on update: during development the #OnApplicationStart may execute several times, as Play may automatically reload the application when you do certain code changes. This is part of the dev process (the same that an #OnApplicationStart job won't start in Dev until the server gets a request).
As it's a job that you only want to run once, you may try to skip it in dev mode using the check:
if(Play.mode == Play.Mode.DEV)
If you need to run it at least once, add a dev-only url that you can access during dev to start the process.
Now, on your update you also mention that you are calling that code in a controller, and that every time the controller is acessed the method is called. That's expected. Singleton doesn't mean that it will run only once, but that there is only 1 object in the system. If in your controller you launch the calculation, that will happen everytime you access the controller.
SECOND EDIT (on comments): Arasu, the other issue is that you are calling the method load() when you construct the object. A singleton doesn't garantee that the object will only be constructed once. It garantees that, once constructed, only 1 object will exist. But it may happen that the object is removed by GC, in this case as per your code if you construct it again then you'll call load() and redo the processing.
The best solution is to not call "load" on constructor, but to force the user (you) to call it after retrieving the instance. An alternative is to set some flag at the beginning of load that detects if the code has been run. Be aware that Play is stateless, so that flag will need to be stored in the database.
the defition of a singleton is that it can run only once, it's practically the nature of the pattern. If you somehow manage to run it multiple times, you might have implementation errors in your singleton.
Recheck the singleton pattern in Wikipedia.
Edit:
This code makes it impossible to fetch more than one instance. How would you get more than one?
public class Singleton {
private static Singleton _instance;
private Singleton() { }
public static synchronized Singleton getInstance() {
if (null == _instance) {
_instance = new Singleton();
}
return _instance;
}
}
Or do you mean that you instanciate the Singleton class, instead of calling Singleton.getInstance()?
It is possible to have a Singleton doing a time consuming processing and be called the same time by two different threads. I think this is the situation here. The same Singleton object's method is called multiple times from the program.
I have run a little test... two thread calling the same Singleton object and here is the result
Thread[Thread 1,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 2,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 1,5,main] internal loop number = 1 Object = example.Singeton#164f1d0d
and here is the code.
package example;
public class Singeton {
private static final Singeton INSTANCE = new Singeton();
private Singeton() {}
public static Singeton getInstance(){
return INSTANCE;
}
public boolean doTimeConsumingThing(){
for (int i=0; i<10000000;i++){
System.out.println(Thread.currentThread() + " internal loop number = " + i + " Object = " + toString());
}
return true;
}
}
package example;
public class MulThread extends Thread{
public MulThread(String name) {
super(name);
}
#Override
public void run() {
while(true){
Singeton s = Singeton.getInstance();
System.out.println("Thread " + getId());
s.doTimeConsumingThing();
}
}
public static void main(String[] args) {
MulThread m1 = new MulThread("Thread 1");
MulThread m2 = new MulThread("Thread 2");
m1.start();
m2.start();
}
}
Please correct my notion above if i am wrong.
Hence what you need is a variable to keep track of the state of the time consuming procedure (i.e. a boolean isRunning) or the times the procedure has been called.
You can also make the pertinent time consuming method of the Singleton synchronized so only one thread can access the method while it is running (in my example if you make the doTimeConsumingThing() synchronized, the second thread will block until the singleton's method called from the first thread is finished.
Hope it helps
I had the same problem in DEV mode, and what I did is create a module for the tasks I don't want to be run at every #OnApplicationStart.
The trick is to launch those tasks in a overriden "onLoad()" method, in the module:
public void onLoad()
{
// tasks to run one time only
}
The onLoad() method is called one time only, not each time the application is restarted.
I don't know if this will help, but here are some things to check:
The code in your question is not thread-safe. You're missing the synchronized keyword in getInstance. That could cause the constructor to be called more than once by different threads.
Could DataGridManagerImpl be getting loaded by different classloaders? That static instance variable isn't static for the whole JVM, just static for that class' classloader.
load is public. Could some other code being calling that method?
The entry point into a program in java is typically something like this
// MyMain.java
public class MyMain{
//whatever
public static void main(String args[]){
System.out.println("balderdash");
}
}
However, since there is only the one SOP in main, the above class may be like this instead
// MyMain.java
public class MyMain{
//whatever
static {
System.out.println("balderdash");
}
}
One obvious advantage to using main(...) is that arguments may be passed in to the program.
Another ( I'm guessing here ) may have to do with the garbage collecter treating objects created within a static block differently.
What other benefits come from using the language-defined entry-point - public static void main( String args[] ) instead of using a static initializer.
p.s. The above snippets are for illustration only, and may not be compilable
You can test it or call it from other applications.
It's what other people will expect.
If you execute your whole application in the context of a static initializer, I suspect you'll effectively be holding a lock on that type for the whole time. If any other thread tries to call a static method in the same class, it will block. That's the sort of problem you get when you try to use a concept in an unexpected way - it's just conceptually "wrong". Initializing the class simply isn't the same as running an application.
EDIT: Here's an example of that problem:
class SampleTask implements Runnable
{
public void run()
{
System.out.println("Calling someStaticMethod");
Test.someStaticMethod();
System.out.println("someStaticMethod returned");
}
}
public class Test
{
static
{
System.out.println("Starting new thread...");
new Thread(new SampleTask()).start();
System.out.println("Thread started. Sleeping");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
System.out.println("Interrupted!");
}
System.out.println("Finished sleeping");
}
public static void someStaticMethod()
{
System.out.println("In someStaticMethod");
}
public static void main(String[] args)
{
System.out.println("In main. Sleeping again.");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
System.out.println("Interrupted!");
}
}
}
Output:
Starting new thread...
Thread started. Sleeping
Calling someStaticMethod
Finished sleeping
In someStaticMethod
someStaticMethod returned
In main. Sleeping again.
Note how the call to someStaticMethod from the new thread has to wait until the static initializer has finished before it gets to run.
You can call main() for other objects from anywhere else in your code as many times as you want. A static initializer is only going to ever run once. Also, you can pass parameters from the command line into main().
Two big plusses for main() in my book.
The main reason why it's better to use main() is that you can have several main methods in your application (in different classes). If you load a class, main() isn't executed automatically while static code blocks are always executed exactly once at the first time a class is loaded and there is no way to prevent that.
OK, I'll admit that I haven't tried it with a static initialized class, but wouldn't typing
java StaticInitializedClass
on the command line print out
Exception in thread "main" java.lang.NoSuchMethodError: main
since it doesn't have a main(String[]) method?
Let's not forget about maintainability. When someone else goes to change your code they are always going to look for a main() method to start the program. Unless there is some reason you can't get around (and I'm guessing there is not) then I would just use the main method.
If you don't have any entry point, you cannot run anything. If you have many entry points (many main methods), user who starts your application controls which will be run by command line.
On the other hand static initialization blocks are executed when class is loaded. Controlling which class is loaded and the order of class loading (and of executing their static initialization blocks) is much harder to control. That's enough reason not to put to much logic to static initialization blocks. You make something harder to read and understand and in reward you receive something harder to use.