log4j methods: instance or class?

C

Charles T. Smith

The javadocs for getLogger() says

If the named logger already exists, then the existing instance will be
returned. Otherwise, a new instance is created.

Another words, it's an instance (non-static) method.

An example program I have (using the old interface) is:

static Category log = Category.getInstance(Css.class.getName());

It's stored in a static variable.

Is this wrong?

If it's not wrong, does that mean that all threads share the same
reference? If they do, does that mean that log4j automatically sequences
access?
 
C

Charles T. Smith

The javadocs for getLogger() says

If the named logger already exists, then the existing instance will be
returned. Otherwise, a new instance is created.

Another words, it's an instance (non-static) method.

An example program I have (using the old interface) is:

static Category log = Category.getInstance(Css.class.getName());

It's stored in a static variable.

Is this wrong?

If it's not wrong, does that mean that all threads share the same
reference? If they do, does that mean that log4j automatically sequences
access?



Okay, I've learned a little bit more. I ran the following test program
and realized that you can create the logger either way, with slightly
different semantics, depending.

The question remains: if statically declared, does the logger do its own
sequencing, or is the user headed for trouble in a threaded environment?



import org.apache.log4j.Category;
class log4j {
// either (seem to) work for both static and non-static callers.
//
// No.
// With static, it can be called from main() or sub.
// Without static it can only be called from sub.
static Category log = Category.getInstance(log4j.class.getName());
// Category log = Category.getInstance(log4j.class.getName());

// Note that 'int count' can't be referenced from (static) main()
// but 'static int count' *can* be referenced from (non-static) sub()
// int count = 0;
static int count = 0;

public static void main (String[] args)
{
log4j logger = new log4j ();
// note that you can call log.debug only when it's declared to be static
log.debug("main: entered");
System.out.println ("hello world");
logger.sub();
// you can call logger.log.debug whether it's static or not
logger.log.debug ("main: " + count);
}

public void sub ()
{
log.debug("sub: entered");
count++;
}
}
 
L

Lew

That is not a rephrase but a completely different and incorrect statement.

getLogger() is a static method of the Logger class. What it returns is an
instance, but the method doesn't belong to that instance.

You do not need to use getName() - log4j was actually designed to use the
class itself as the argument to the factory method, which confers certain
advantages to tuning log capabilities at runtime.

Logger logger = Logger.getLogger( getClass() ); // instance version

I prefer the Logger class to Category. What Apache says about Category:
This class has been deprecated and replaced by the Logger subclass. It will be kept around to preserve backward compatibility until mid 2003.
(The first sentence, "... deprecated ...", is in bold face and red in the
Javadoc.)

Let's see, what month is it now?
Internally, whenever log4j is asked to produce a Category object, it will instead produce a Logger object. Log4j 1.2 will never produce Category objects but only Logger instances.

Seriously, what made you decide to go with Category?

Some say any use of non-constant static variables is suspect at least, and
likely wrong. I personally prefer to use an instance variable, but you must
use a static logger in static methods.

Yes, but don't worry. log4j built thread-handling into their methods. In
fact, you can control how the output looks to show which thread is logging.
Okay, I've learned a little bit more. I ran the following test program
and realized that you can create the logger either way, with slightly
different semantics, depending.

The creation of the logger has identical semantics either way, regardless.
The question remains: if statically declared, does the logger do its own
sequencing, or is the user headed for trouble in a threaded environment?

Do you mean if your logger variable is static, could you be heading for
trouble? Not AFAIK from log4j. They build Logger to handle multi-threaded
logging. In fact, you usually emit a thread identifier in your logging output
to help disentangle what you're reading therein.
import org.apache.log4j.Category;
class log4j {

This is an inadvisable name for the class since it is the same as the name of
an external package, one even used by the class. This makes the code harder
to grok. It also doesn't follow Sun's recommendation to name classes with an
initial upper-case letter.
static Category log = Category.getInstance(log4j.class.getName());

This is where it is strange to see what looks like a package name as a
function argument.
// Category log = Category.getInstance(log4j.class.getName());
// Note that 'int count' can't be referenced from (static) main()
// but 'static int count' *can* be referenced from (non-static) sub()

Sure, because the instance has access to the class but not vice versa.
Nothing earth-shattering there.
// int count = 0;
static int count = 0;

public static void main (String[] args)
{
log4j logger = new log4j ();

This is even more confusing. Typically "logger" would be used as an instance
of the Logger class from the log4j package.
// note that you can call log.debug only when it's declared to be static

You cannot call instance methods or refer to instance variables from static
methods by the definition of static.
log.debug("main: entered");
System.out.println ("hello world");
logger.sub();
// you can call logger.log.debug whether it's static or not
logger.log.debug ("main: " + count);

Right, because you call your example instance 'logger' and your logger 'log'.

Your observations are correct and the example shows them well. They pertain
to static versus instance ownership, not so much to the log4j library as such;
the illustrated principles are fundamental to Java programming.

Sun recommends that class names begin with upper-case letters, non-constant
variables (seems redundant, that phrase) and methods should start with
lower-case letters. Both should start each "internal word" (compound word
part) with its own initial capital letter. Compile-time constants should be
named with all upper-case letters, and separate compound word parts with
underscores, according to Sun's guidelines.

public class InitialUpperCaseLetter
{
private static final String CONSTANT_ALL_UPPERCASE = "";
int variableInitialLowerCase;
public void methodInitialLowerCase()
{
}
}

The use of mixed upper- and lower-case letters, sometimes called "camel case",
or more fetchingly, "camelCase", aids readability.
 
C

Charles T. Smith

That is not a rephrase but a completely different and incorrect statement.

getLogger() is a static method of the Logger class. What it returns is an
instance, but the method doesn't belong to that instance.


Am I correct in saying that the error in my rephrase (other the
grammatical error of "Another words" instead of "In other words" :)
is that I said *method* and should have said *object* (i.e. that what gets
returned)?

You do not need to use getName() - log4j was actually designed to use ....

Seriously, what made you decide to go with Category?


I guess I didn't make clear that the example I was looking at was legacy
code.

Some say any use of non-constant static variables is suspect at least,
and likely wrong. I personally prefer to use an instance variable, but
you must use a static logger in static methods.


Okay, that implies optionality. I guess I was starting to see a truth
table:

class/instance static/non
c s ok
c n ?
i s ?
i n ok


Your point about "constant" seems to bring in a new dimension that
overloads my circuits.

Yes, but don't worry. log4j built thread-handling into their methods.


from the same instance (see below)?

The creation of the logger has identical semantics either way,
regardless.


I meant, for example, whether the logger could be used from within static
methods or not.

Do you mean if your logger variable is static, could you be heading for
trouble? Not AFAIK from log4j. They build Logger to handle
multi-threaded logging. In fact, you usually emit a thread identifier
in your logging output to help disentangle what you're reading therein.



But can both threads use the same - global and static - instance
reference? This is the key question.

In this case, not only the core resources of the logger would have to be
protected against concurrent access, like the file and buffer, but even
any instance-specific resources.


This is an inadvisable name for the class since it is the same as the
name of an external package, one even used by the class. This makes the
code harder to grok. It also doesn't follow Sun's recommendation to
name classes with an initial upper-case letter.


Okay, sorry. I should have called it HelloWorld.
 
L

Lew

Am I correct in saying that the error in my rephrase (other the
grammatical error of "Another words" instead of "In other words" :)
is that I said *method* and should have said *object* (i.e. that what gets
returned)?

No. An object already is an instance; "instance object" is redundant.
I guess I didn't make clear that the example I was looking at was legacy
code.

Ah. That explains it. This must be some legacy; log4j has deprecated
Category for quite some time now.
Okay, that implies optionality. I guess I was starting to see a truth
table:

class/instance static/non
c s ok
c n ?
i s ?
i n ok

What do you mean here? What is "ok" or not? What is optional?

The keyword "static" implies that ownership of the member variable, class or
method is in the class; the class itself is a sort-of "object" with its own
variables and methods. Absence of the "static" modifier means that the member
variable, class or method is in the instance; it belongs to the individual
object. Each individual instance knows about the class that spawned it.
Obviously there is no way for the class "object" to be aware of the unbounded
set of instances it spawned. The turtle lays its eggs and returns to the sea
having never seen its hatchlings.
Your point about "constant" seems to bring in a new dimension that
overloads my circuits.

Read the tutorials on the Sun site.

Yes, if the reference is to the same-named instance but not otherwise, and yes.
I meant, for example, whether the logger could be used from within static
methods or not.

The /use/ of the logger has different semantics, as with any static or
non-static reference. The /creation/ of the logger instance is not different.

This is the definition of the keyword "static". Have you read up on it?
But can both threads use the same - global and static - instance
reference? This is the key question.

And you've received the key answer several times in my post. Check out the
documentation at the log4j web site.
In this case, not only the core resources of the logger would have to be
protected against concurrent access, like the file and buffer, but even
any instance-specific resources.

Have you tried the log4j documentation on their website?
(stuff about code conventions recommended by Sun.)
Okay, sorry. I should have called it HelloWorld.

Imaginative. No need to apologize. The advice was for your benefit, not mine.

You will find the Sun tutorials on the matter of "static" and the Java
Language Specification on the matter to be helpful.
 
C

Charles T. Smith

Ah. That explains it. This must be some legacy; log4j has deprecated
Category for quite some time now.


I can remember a time before java even existed!

What do you mean here? What is "ok" or not? What is optional?


If a thing is a class, then it is knowable inside (and outside) all
instances. The same (roughly?) is true with statics.

If a thing is an instance, then it is knowable only within the instance
that defines it. The same (roughly?) is true with non-statics.

If a thing is only meaningful as an instance (because of its dynamic
nature) then would it be an error to assign it to a static variable,
which makes it available to other instances?

I was greatly surprised that java would let me assign the logger to
either a static or a non-static variable.

This is the definition of the keyword "static". Have you read up on it?


Well, yes, N times (but not yet N+1 times).

And you've received the key answer several times in my post. Check out
the documentation at the log4j web site.


Have you tried the log4j documentation on their website?


Well, yes, but perhaps not deep enough. There is the following line in
http://logging.apache.org/log4j/docs/manual.html:

Thus, it is possible to configure a logger and then to retrieve the same
instance somewhere else in the code without passing around references.

the question I'm dealing with is, *can* you pass around references in the
code?

It's a JNI application and I don't want the native code to have go
searching for the logger instance every time it wants to trace something.
I also don't have state flowing from procedure to procedure. So, I'd
like to make the pointer a global variable (yuk). Normally I avoid that,
but the documentation seems to imply that all threads could share it
without problem. But that seems like a mighty sequencing task for any
code.


I'm suggesting that there might be two levels of thread-safety here. I
haven't seen anything in either java or log4j document that discusses that.

I also don't know how I would test it programmatically.
 
L

Lew

Charles said:
If a thing is a class, then it is knowable inside (and outside) all
instances. The same (roughly?) is true with statics.

If a thing is an instance, then it is knowable only within the instance
that defines it. The same (roughly?) is true with non-statics.

If a thing is only meaningful as an instance (because of its dynamic
nature) then would it be an error to assign it to a static variable,
which makes it available to other instances?

I was greatly surprised that java would let me assign the logger to
either a static or a non-static variable.

why? You can assign references to static members to an instance member. E.g.,

public class Foo
{
private static final int ZERO = 0;
private int val;
public void bar()
{
val = ZXRO;
}
}

It's very widely done. As I have mentioned a few times, static members are
visible to instances.
There is the following line in
http://logging.apache.org/log4j/docs/manual.html:

Thus, it is possible to configure a logger and then to retrieve the same
instance somewhere else in the code without passing around references.

the question I'm dealing with is, *can* you pass around references in the
code?

Yes.
 
L

Lew

Lew said:
why? You can assign references to static members to an instance member.

Furthermore, the result of "Logger.getLogger( something )" is neither static
nor non-static.
 
C

Charles T. Smith

why? You can assign references to static members to an instance member.
E.g.,

public class Foo
{
private static final int ZERO = 0;
private int val;
public void bar()
{
val = ZXRO;
}
}
}
It's very widely done. As I have mentioned a few times, static members
are visible to instances.


Hmmm. There's a new concept for me - "visible". Visible == usable?

I'm not yet completely clear on the permutations of all of that, but I
expect experience will clear it up for me.



Ok, that's good news. Thank you for you help.
 
C

Charles T. Smith

Furthermore, the result of "Logger.getLogger( something )" is neither
static nor non-static.


Wow. That makes it really hard to understand. For example, the JNI spec
says about GetFieldID() (to take the one that's currently sitting in my
browser):

Returns the field ID for an instance (nonstatic) field of a class.
The field is specified by its name and signature...

So, the results of methods can be static, nonstatic, or something else
altogther. Tri-state, so to speak.


Sorry, I'm obtuse. But while I've got your attention, can you say what
the fully-qualified-class name of the logger would be (for GetFieldID())?

Would it be:
- org.apache.log4j.???
- java.lang.object (or whatever along this line)
- my.application.name
 
L

Lew

Charles said:
Wow. That makes it really hard to understand. For example, the JNI spec
says about GetFieldID() (to take the one that's currently sitting in my
browser):

Returns the field ID for an instance (nonstatic) field of a class.
The field is specified by its name and signature...

So, the results of methods can be static, nonstatic, or something else
altogther. Tri-state, so to speak.

No. Results of methods can never be static or non-static. Those are
attributes of class member identifiers, not objects.

The result of a method is a value, either void, a primitive or an object.
These are runtime results, not members of a class, so the keyword "static" is
not relevant. "static" is an attribute of class members, of which there are
three kinds: class definition, variable or method. The return result of a
method is not a member, but might be assigned to a member.

Let me say this again: The result of a method is neither static nor non-static.

The method itself might be static or not. The difference is how you invoke
the method, not what the result is. To invoke a method, you must refer to its
owner, which is either a class for static methods, or an object for instance
methods. It is the method that has the attribute, not the result of it.

You might then assign the result to another variable. Whether that variable
is static or not is a question for the method making the call, but has no
bearing on the reference that the variable will hold.

Really, read up on the meaning of "static".
I expect experience will clear it up for me.

Not without study it won't.
 
C

Charles T. Smith

No. Results of methods can never be static or non-static. Those are
attributes of class member identifiers, not objects.

The result of a method is a value, either void, a primitive or an object.
These are runtime results, not members of a class, so the keyword "static"
is not relevant. "static" is an attribute of class members, of which
there are three kinds: class definition, variable or method. The return
result of a method is not a member, but might be assigned to a member.


Okay, that makes sense - values vs. variables. I guess I have to parse
that quote above differently.



That's a good reference.

Not without study it won't.


:)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,430
Messages
2,571,676
Members
48,796
Latest member
Greg L.

Latest Threads

Top