Dawid
Dawid

Reputation: 4062

"$0 (Program Name) in Java? Discover main class?" again

I have found following question: $0 (Program Name) in Java? Discover main class? but accepted answer fails in this situation:

public class Derived extends Base { }

class Base {
    public static void main(String[] args){
        System.out.println(getTheClassName());
    }

    static String getTheClassName(){
        StackTraceElement[] stack = Thread.currentThread().getStackTrace();
        StackTraceElement main = stack[stack.length - 1];
        return main.getClassName();
    }
}

When calling:

java Derived

the output is unfortunately Base not Derived as expected.

Is it possible to get the name of real main class? (btw. jps tool detects main class correctly but to get the proper name I need to know ID of current VM, and that is also a problem)

Best regards.

Edit: to be precise: I need to know what is the name of class passed as command line argument passed to JVM. jps tools does it the way I want, but I cannot use this tool because of other problems (such as unknown VMid).

Edit2: replying globally to Thorbjørn's answer:

For your approach to work, you need to have a non-static method instead. Make it non-static, have a main() in Derived doing a new Derived().getTheClassName()

I am wondering I can get the name without implementing main method in Derived class.

Solution: I will provide both (Thorbjørn's and erickson's) mechanisms of an initialization of Derived class ;-) All of the answers were very helpful. I accepted Thorbjørn's becase he posted his answer earlier than erickson. Thank You.

Upvotes: 2

Views: 4694

Answers (3)

erickson
erickson

Reputation: 269647

Why would you expect Derived when the main entry-point is in Base? Members that are declared static belong to their class and are not inherited. When running the program as is, the class Derived will not even be loaded, as it is never referenced.


Consider taking the derived class's name as an argument to the Base class. In addition to making the target class explicit, it might be a convenient place to implement other features.

class Base {
  public static void main(String... argv) throws Exception {
    Class<?> clz = Class.forName(argv[0]);
    Method mth = clz.getMethod("main", String[].class);
    String[] sub = new String[argv.length - 1];
    System.arraycopy(argv, 1, sub, 0, sub.length);
    mth.invoke(null, sub);
  }
}

Upvotes: 3

Colin Hebert
Colin Hebert

Reputation: 93157

Try this:

for(final Map.Entry<String, String> entry : System.getenv().entrySet()){
    if(entry.getKey().startsWith("JAVA_MAIN_CLASS"))
        return entry.getValue();
}

But still you should look at others answers. Even if this works, it's a really bad practice.

Upvotes: 1

Static methods belong to the class they are defined in, and not the instance of the class (same as static/non-static methods). Hence when you are inside getTheClassName you are in a static method defined in the Base class.

For your approach to work, you need to have a non-static method instead. Make it non-static, have a main() in Derived doing a new Derived().getTheClassName()

Upvotes: 5

Related Questions