How to initialize static blocks? - java

I have to work with a bunch of static legacy classes that contain static blocks.
The classes itself are only helper classes with only static methods.
Example:
public abstract class Legacy {
protected static final String[] ARRAY;
static {
//init that ARRAY
}
public static String convert(String value) {
//makes use of the ARRAY variable
}
}
Important: I don't have control over the sources and thus cannot modify the code. I know that this is a serious design flaw in how the class is build.
Problem: when accessing the class concurrently, I get exceptions from the legacy classes if the class is not initialized yet. So I have to ensure at application startup that each static class was initialized properly before.
But how could I do this?
I tried as follows:
Legacy.class.newInstance();
But that results in the following error:
java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
So probably I'm doing it wrong?

Static initializers are thread safe in that they will only be run, and by a single thread.
They may run multiple times if the class is loaded by more than one classloader, but in that case they are effectively initializing a different class.
It is therefore unlikely that the problem you are seeing is due to incomplete initialization.
It seems more likely that your convert method is doing something that is not thread safe such as modifying the array.

If you call only static methods of the legacy classes there is no need to create an instance. The static block will be executed only once (the JVM will take care of it).
See this small example.
class Legacy {
static {
System.out.println("static initializer of Legacy");
}
public static void doSomething() {
System.out.println("Legacy.doSomething()");
}
}
class LegacyDemo {
public static void main(String[] args) {
Legacy.doSomething();
}
}
If you run LegacyDemo it will print
static initializer of Legacy
Legacy.doSomething()

Related

is FindBugs 'JLM_JSR166_UTILCONCURRENT_MONITORENTER' safe to ignore in this case

I have a library that I am required to use that has a dangerous initialization of a static value (the classes have been stripped down to the minimum for the example):
public TheirBaseClass {
public static String PathToUse = null;
public BaseClass(){
PathToUse = "Configured";
// ...
// do some other stuff with other side effects
// ...
}
}
I have a case where I attempt to read from the value ConfigValue without instantiating the class (to avoid some of the sideeffects).
Paths.get(TheirBaseClass.PathToUse).toFile()....
This causes a NullPointerException
Because I am required to use this class, I am looking to inherit from it, and attempt to take action to ensure that initialization has taken place when accessing the static.
public MyBaseClass extends TheirBaseClass{
private static final AtomicBoolean isInitialized = new AtomicBoolean(false);
static {
MyBaseClass.Initialize();
}
public static void Initialize(){
// FindBugs does not like me synchronizing on a concurrent object
synchronized(isInitialized){
if( isInitialized.get() ){
return;
}
new TheirBaseClass();
isInitialized.set(true);
}
}
public MyBaseClass(){
super();
}
}
Which allows me to
MyBaseClass.Initialize();
Paths.get(MyBaseClass.PathToUse).toFile()....
This seems to be working reasonably well (and resolves some other phantom defects we've been having). It allows TheirBaseClass to function naturally, while allowing me to safely force initialization in the couple of cases I may need to.
However when I run FindBugs against this code, I get JLM_JSR166_UTILCONCURRENT_MONITORENTER. After reading the description, I agree that the use of AtomicBoolean could be dangerous because someone else could change the value, but...
I think its safe to ignore in this case (but have a doubt)
I generally prefer to rewrite code than put an ignore marker in place
Am I actually doing something dangerous (and just don't see it)? Is there a better way to do this?
Unfortunately, using a different TheirBaseClass is not an option.
Related
Are Java static initializers thread safe?
You might find it easier to adapt the lazy holder idiom:
public MyBaseClass {
private static class Initializer {
static {
new TheirBaseClass();
}
// Doesn't actually do anything; merely provides an expression
// to cause the Initializer class to be loaded.
private static void ensureInitialized() {}
}
{
Initializer.ensureInitialized();
}
// Rest of the class.
}
This uses the fact that class loading happens only once and is synchronized (within a single class loader). It happens only when you instantiate a MyBaseClass.

How-to create a static java API?

I saw someone writing a java LOG API like the code unerneath.
The idea is that the Client does not have to invoke LogUtil.getInstance() every time.
But my feelings are this is not idiomatic java?
public class LogUtil{
private static LogUtil instance;
private Object current;//some Logger
private static LogUtil getInstance(){
if(instance == null){
instance = new LogUtil();
}
return instance;
}
private static void debug(String text){
}
public static LogUtil init(){
//dosomething with
// getInstance().current;
return getInstance();
}
public static LogUtil logSomething(String text){
//dosomething with
// getInstance().current;
return getInstance();
}
public static LogUtil anotherMethod(String text){
//dosomething with
// getInstance().current;
return getInstance();
}
}
What are the arguments against such a design (making every method static)?
This is basically a variant of "global variables" and the problem is always the same: You can have only one of them. If you ever need to replace or extend this, lot of code will break.
Which why other logging frameworks use factories:
private final static Logger log = LoggerFactory.getLogger( Foo.class );
That way, I have a single global variable (instead of dozens in your case). It's not ideal but give me at least a single point of failure.
This approach allows me to extend / replace the Logger interface with almost anything without having to change hundreds of places in my code.
That said: Don't write your own logging API. Use slf4j. It will take you a bit longer to understand how it works but many clever people have spent years to build a great logging framework that solves thousands of problems that you don't know about, yet.
EDIT
its not ecactly a general loging util. but more a "Reporter class" which produces Business Word documents.
Then have a look at static imports.
I would suggest to expose a single getInstance() method but give that method a more useful name. You can then import this single method statically everywhere else and call it without the LogUtil. prefix.
static classes are Helper classes, for your LogUtil static class i would declare all methods to return void:
public class LogUtil{
private static LogUtil instance = new LogUtil(); //Initialization here
private Object current;//some Logger
private static LogUtil getInstance(){
}
private static void debug(String text){
}
public static void init(){
//dosomething with
// instance.current;
}
public static void logSomething(String text){
//dosomething with
// instance.current;
}
public static LogUtil anotherMethod(String text){
//dosomething with
// instance.current;
}
}
But I'm not comfortable with that design, the use of a LogUtil is to create a Logger depending on configuration preferences, and return it, which have instance methods, like log4j you can have ConsoleLog, FileLog, RemoteLog, etc
Author of this class would probably want to build a fluent interface, explaining why getInstance would be hidden for other class's method calls and explaining the return type not being void.
Benefit of this would allow client to make the method calls cleaner:
LogUtil.init().logSomething("something").anotherMethod("text");
The whole reduced to one line so.
I'm not dealing with the "static" debate, since as Aaron said above, static is often often often not recommended since it breaks flexibility/extensibility and is anti-OO.
One rule-of-thumb for making method static is: ask yourself "does it make sense to call this method, even if no Obj has been constructed yet?" If so, it should definitely be static."
In your example, operations like logSomething(), anotherMethod() are doing something with instance. Since these methods don't make sense without instance, they should be non-static. Only getInstance() method should be static.
Main disadvantage of making everything static is you cannot swap, override or choose method implementations at runtime. This thread has good discussion on disadvantages of static: In Java, is there any disadvantage to static methods on a class?.

how to load a java class along with static initializations before they are used?

I need to load some classes along with their respective static initializations, for example, in a factory method implementation.
If I just make reference to the class using the below syntax, the JVM does not run the static initialization part. Actually, does the JVM even load the classes?
Class<Shape> shapeClass = Shape.class;
or
Shape s = null;
But with class.forname() it does execute static initializations.
Class.forname("Shape");
The question is if this is the only way to do load a java class along with static initializations? Or are there other ways? Any significant performance penalties for using class.forname()?
From Class.forName(String className) API: Invoking this method is equivalent to: Class.forName(className, true, currentLoader).
The second argument = true means initialize class, and initialize class means run static initializers
This is a test to check
package test;
class Test2 {
static {
System.out.println("static init");
}
}
public class Test1 {
public static void main(String[] args) throws Exception {
Class.forName("test.Test2");
}
}
output
static init
but if you load Test2 with
Class.forName("test.Test2", false, ClassLoader.getSystemClassLoader());
there will be no output. You can also use this test to see that Test.class.getName() does not load the class either.
The simplest way to make it load is to add an empty static method and call it:
class Test2 {
public static void load() {
}
...
Test2.load();
When you load/resolve a class, the static initializers are executed in the order they are defined. It shouldn't matter how you load them, reflection or not. That is, unless you're meaning some other sort of initialization?

Need help to get two classes to assist each other

i'm currently just fooling around with different classes to test how they work together, but im getting an error message in NetBeans that i cant solve. Here's my code:
class first_class.java
public class first_class {
private second_class state;
int test_tal=2;
public void test (int n) {
if (n>2) {
System.out.println("HELLO");
}
else {
System.out.println("GOODBYE");
}
}
public static void main(String[] args) {
state.john();
TestingFunStuff.test(2);
}
}
class second_class
public class second_class {
first_class state;
public int john () {
if (state.test_tal==2) {
return 4;
}
else {
return 5;
}
}
}
Apparently i can't run the method "john" in my main class, because "non static variable state cannot be referenced from a static context" and the method "test" because "non static method test(int) cannot be referenced from a static context".
What does this mean exactly?
Screenshot of the error shown in netbeans: http://imageshack.us/photo/my-images/26/funstufffirstclassnetbe.png/
It means state must be declared as a static member if you're going to use it from a static method, or you need an instance of first_class from which you can access a non-static member. In the latter case, you'll need to provide a getter method (or make it public, but ew).
Also, you don't instantiate an instance of second_class, so after it compiles, you'll get a NullPointerException: static or not, there needs to be an instance to access an instance method.
I might recommend following Java naming conventions, use camelCase instead of under_scores, and start class names with upper-case letters.
The trick here to get rid of the error message is to move the heavy work outside of main. Let's assume that both lines are part of a setup routine.
state.john();
TestingFunStuff.test(2);
We could create a function called setup which contains the two lines.
public void setup() {
state.john();
TestingFunStuff.test(2);
}
Now the main routine can call setup instead, and the error is gone.
public static void main(String[] args) {
setup();
}
However, the other members are correct in that your instantiation needs some cleanup as well. If you are new to objects and getting them to work together might I recommend the Head First Java book. Good first read (note first not reference) and not all that expensive.
Classes can have two types of members by initialization: static and dynamic (default). This controls the time the member is allocated.
Static is allocated at class declaration time, so is always available, cannot be inherited/overridden, etc. Dynamic is allocated at class instantiation time, so you have to new your class if you want to access such members...
It is like BSS vs heap (malloc'd) memory in C, if that helps..

Java syntax question

What does
static{
//something
}
declared inside a class definition body mean?
public class A extends B{
static {
C.register(new C(A.class,
(byte) D.x.getCode()) {
public DataSerializable newInstance() {
return new A();
}
}
);
}
}
The static block is called a "static initialization block." It is very similar to a regular constructor except that it can only initialize static variables.
I have found it to be useful when initialization of some static variable may throw an exception that you would like to handle or at least log. It is especially useful in the initialization of static final variables.
You may read more about static initialization blocks here: Initializing Fields
It executes a block of code without requiring an instance of this class, i.e. as soon as the class loader loads the class.
That becomes a static initialisation block, which can be written as a static method.
It's a static initializer. It's run once the class is loaded and it's results can be stored in static members. It's used to initialize static members that require more than the regular new Xyz() (like Lists or Maps)...
It's a static initializer. It lets you specify things that happen at the time that the class is loaded, before any instance is created.
If an exception is thrown from a static initializer it's very confusing, it's hard to tell where it came from. Anything that you do in a static initializer should have a try-catch around it and have the exception get logged. It's a good language feature to avoid if you can.
It means that you will have this section which is inside the static block extecuted FIRST on load of the class into the JVM.
Execute the following simple program might make things clearer
public class Test123 {
static{
System.out.println("Hello from static block");
}
public static void main(String[] args) {
System.out.println("In main");
}
}
The output to the above will be
Hello from static block
In main

Categories

Resources