Portable way to find name of main class from Java code - java

Is there any way to find the name of the main class used to launch the current JVM, from arbitrary code running in that JVM?
By arbitrary, I mean that the code is not necessarily running in the main thread, or may be running in the main thread before main has even been called (e.g., code in a user-supplied java.system.classloader, which runs before main since it's used to load main) - so examining the call stack is not possible.

This is the closest I can get and you can take it from here.I can not guarantee that it is truly portable and it will not work if any method is invoking main method of another class.Let me know if you find more clean solution
import java.util.Map.Entry;
public class TestMain {
/**
* #param args
* #throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(findMainClass());
}
public static String findMainClass() throws ClassNotFoundException{
for (Entry<Thread, StackTraceElement[]> entry : Thread.getAllStackTraces().entrySet()) {
Thread thread = entry.getKey();
if (thread.getThreadGroup() != null && thread.getThreadGroup().getName().equals("main")) {
for (StackTraceElement stackTraceElement : entry.getValue()) {
if (stackTraceElement.getMethodName().equals("main")) {
try {
Class<?> c = Class.forName(stackTraceElement.getClassName());
Class[] argTypes = new Class[] { String[].class };
//This will throw NoSuchMethodException in case of fake main methods
c.getDeclaredMethod("main", argTypes);
return stackTraceElement.getClassName();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
}

Related

NoSuchMethodException not caught [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I am trying to catch the NoSuchMethodException in the following code:
try {
method = currentClass.getMethod(arg1,arg2);
break;
}
catch (NoSuchMethodException e) {
System.out.println("hi");
}
It's not getting caught. I've tried catch (Throwable e) and catch (Exception e) and catch (NoSuchMethodError e) but none of them worked.
Even though When I run the code the console shows a NoSuchMethodException, but it's not getting caught.
You are using getMethod in a wrong way. You must pass the name of the method and an array of arguments to it. Given below is an example of the correct way:
class Main {
public static void main(String[] args) {
try {
Class[] arguments = new Class[1];
arguments[0] = String.class;
String.class.getMethod("concat", arguments);
} catch (NoSuchMethodException e) {
System.out.println("Error occured");
}
}
}
Check the signature of String#concat which takes an argument of type, String.
Another example:
class MyClass {
public void hello(String name) {
System.out.println("Hello " + name);
}
public int getSum(int x, int y) {
return x + y;
}
}
class Main {
public static void main(String[] args) {
try {
Class[] arguments = new Class[1];
arguments[0] = String.class;
MyClass.class.getMethod("hello", arguments);
System.out.println("This one passed.");
arguments = new Class[2];
arguments[0] = int.class;
arguments[1] = int.class;
MyClass.class.getMethod("getSum", arguments);
System.out.println("This one too.");
// The following one will fail
MyClass.class.getMethod("foo");
} catch (NoSuchMethodException e) {
System.out.println("Error occured");
}
}
}
Output:
This one passed.
This one too.
Error occured
Update:
This update is based on the following valuable comment from Holger:
getMethod is a varargs method. There is no need to deal with arrays manually. You can use String.class.getMethod("concat", String.class);,
MyClass.class.getMethod("hello", String.class);, and MyClass.class.getMethod("getSum", int.class, int.class);. In fact, your MyClass.class.getMethod("foo"); statement is already using that feature, as it doesn’t create the zero length Class[] array manually.
class MyClass {
public void hello(String name) {
System.out.println("Hello " + name);
}
public int getSum(int x, int y) {
return x + y;
}
}
class Main {
public static void main(String[] args) {
try {
MyClass.class.getMethod("hello", String.class);
System.out.println("This one passed.");
MyClass.class.getMethod("getSum", int.class, int.class);
System.out.println("This one too.");
// The following one will fail
MyClass.class.getMethod("foo");
} catch (NoSuchMethodException e) {
System.out.println("Error occured");
}
}
}
Java exception hierarchy looks like so:
Throwable
| |
Error Exception
|
RuntimeException
Errors are intended for signaling regarding problems in JVM internals and other abnormal conditions which usually cannot be handled by the program anyhow. So, in your code you are not catching them. Try to catch Throwable instead:
boolean result = false;
try{
result = Settings.canDrawOverlays(context);
}
catch(Throwable e){
Log.e("error","error");
}
Also it's a good idea to read this
There are two variants to this
NoSuchMethodError - which has base class as Error - and is used by compiler to detect absence of the method used or at runtime when you lets say upgrade or downgrade a particular dependent jar and the method is not defined in the class in the new jar included.
NoSuchMethodException - which has base class as Exception, this you usually get when using reflection and the method with 'name' you are trying to access is not defined in that class.
However, both should be caught if you have catch block with Throwable as Throwable is the base of both Error and Exception.
import java.lang.reflect.Method;
public class NoSuchMethodMethodTest
{
public static void checkIfMethodNotExist()
{
try
{
final NoSuchMethodMethodTest noSuchMethodMethodTest = new NoSuchMethodMethodTest();
Class clazz = noSuchMethodMethodTest.getClass();
final Method m = clazz.getMethod("demo", null);
}
catch (NoSuchMethodException e)
{
System.out.println("demo method not exist");
}
}
public static void checkIfMethodExist()
{
try
{
final NoSuchMethodMethodTest noSuchMethodMethodTest = new NoSuchMethodMethodTest();
Class clazz = noSuchMethodMethodTest.getClass();
final Method m = clazz.getMethod("main", String[].class);
}
catch (NoSuchMethodException e)
{
System.out.println("main method exist");
}
}
}

Unable to clone thread - Why?

To my understanding, Following code should generate 4 clones of the local ProcessingThread running, producing an output:
processing 0
processing 1
processing 2
processing 3
However when I try to run this program I am getting :
java.lang.CloneNotSupportedException
public class Test {
public static void main(String[] args) {
Test o = new Test();
try {
o.process(o.new ProcessingThread() {
public void run() {
System.err.println("processing " + index);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void process(ProcessingThread template) throws CloneNotSupportedException {
// Try run 4 parallel processing threads from the supplied template...
for (int i = 0; i < 4; i++) {
ProcessingThread thread = (ProcessingThread) template.clone();
thread.setIndex(i);
thread.start();
}
// ...
}
public class ProcessingThread extends Thread implements Cloneable {
int index;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void setIndex(int i) {
index = i;
}
}
}
Please help me understand this ? and also how to rectify this problem
Just look into the source code of Thread class:
/**
* Throws CloneNotSupportedException as a Thread can not be meaningfully
* cloned. Construct a new Thread instead.
*
* #throws CloneNotSupportedException
* always
*/
#Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
Cloning thread just doesn't make sense.
Thread is not cloneable. Calling super.clone() ends up throwing CloneNotSupportedException because of this.
Threads can't be cloned because, well, that would be a really bad idea. What if the thread was already running, and had grabbed a condition variable... should both the original thread and the clone have a lock on the same variable?
It seems like what you're trying to do is create multiple instances of a worker thread subprogram. An easy way to do this if the underlying subprogram doesn't have any per-instance mutable state is to pass in a Runnable instead, and create (multiple) threads from that. Really, though, depending on your precise use case you might get more mileage out of something like ExecutorService, which may be very similar to what you're trying to (re)implement.
According to the documentation, the Thread class always throws that exception when calling clone. Since you are just calling the Thread's clone method instead of implementing your own, it's always going to throw that exception.
See:
https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#clone()
Instead of using clone() you want to use a Function, or in this case, a lambda to create your tasks.
public class Test {
public static void main(String[] args) {
Test o = new Test();
o.process(ProcessingThread::new);
}
public void process(TaskBuilder template) {
// Try run 4 parallel processing threads from the supplied template...
for (int i = 0; i < 4; i++) {
new Thread(template.build(this, i)).start();
}
// ...
}
interface TaskBuilder {
Runnable build(Test t, int index);
}
static class ProcessingThread implements Runnable {
final int index;
private final Test test;
public ProcessingThread(Test test, int index) {
this.test = test;
this.index = index;
}
#Override
public void run() {
System.out.println(test + " processing " + index);
}
}
}
However, a simpler way of having N tasks in different using a template is to use a parallel stream.
public static void main(String[] args) {
IntStream.range(0, 4).parallel()
.forEach(index -> System.out.println("processing " + index));
}
prints
processing 2
processing 3
processing 0
processing 1
as there is no guarantee as to the order the tasks are processed.

Accessing field in super to report error

I'm not great with java terminology so it will be easier for you to understand via example:
I instantiate a mymethods class from a
Main class:
public class Main()
{
public boolean hasErrors = false;
MyMethods m = new MyMethods(); //cannot use try/catch
public static void main(String[] args){
m.writeToFile("text");
}
}
In the above class, i cannot (i tried) use a try catch to catch a manually thrown FileNotFoundException but apparently such methods cannot be used in that location (wrapping MyMethods m... in try/catch). I had tried to throw that error when my requisite file wasnt found
MyMethods:
public class MyMethods()
{
public MyMethods(){
if(!new File("file.txt").canWrite()){
changeSuper(true);
throw new FileNotFoundException();
}
}
public void changeSuper(boolean b) //does not work
{
super.hasErrors = b;
}
//input more methods etc here
}
Why is it not possible to use try/catch?
How can i report a filenotfound to the main method?
Note that this is from a GUI app in netbeans, but is not the focus here. Program will not compile if try/catch wraps that line
(note to admins/mods: this question needs butchering, but I cannot express my question better myself)
You just need to add the throws keyword to your method, i.e:
public static void myMethod() throws FileNotFoundException{
// Code goes here ...
if( fileNotFound )
throw new FileNotFoundException("File not found.");
}
you can then catch the exception by surrounding your call to the method with a try/catch block:
try {
// Do stuff...
myMethod();
} catch (FileNotFoundException ex){
// Handle error, if thrown...
}

Junit multiple threads

I have a test case that provides arguments and executes the main method of a class. What would be the best approach using Junit to have multiple threads concurrenlty execute the main method of class.
Not sure if TestNG is an option for you, but it's pretty straightforward with it:
#Test(invocationCount = 100, threadPoolSize = 10)
public void myTest() { ... }
This will cause the test method to be invoked 100 times from 10 different threads. If this test passes and you run it a lot, you can be fairly confident that the code under test is multithread safe.
Why would you do that? Is your public static void main(String []) really run by multiple threads? Seems a strange design, that's why I'm making sure.
If, on the other hand, you want to test parallel executions of your program (so each in a separate JVM), it's not the same as multithreaded, and JUnit won't do that, as it executes within the same JVM. You still can do that, no problem, but make sure you know the difference.
Some examples on SO:
Concurrent JUnit testing
How do I test a concurrent Java program which expects cmd line arguments? (some other tools for parallel test execution in separate JVMs)
Here is a lightweight solution:
Here is the Class you want to testing:
package mTTest;
/**
* UUT class is the Unit Under Test. This will be tested.
* It has two simple method:
* push(): sets the message string if it's null, and waits otherwise.
* pop(): if there is any message sets it null and returns it.
*
*/
public class UUT {
String message = null;
synchronized void push(String msg){
while (null != message) {
try {
wait();
} catch (InterruptedException e) {
}
}
message = msg;
notifyAll();
}
synchronized String pop(){
while (null == message) {
try {
wait();
} catch (InterruptedException e) {
}
}
String ret = message;
message = null;
notifyAll();
return ret;
}
}
Here is the Test class. This will be invoked bz the JUnit framework. Rewrite multiTest() method.
package mTTest;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import org.junit.Test;
/**
* This is the JUnit test class. Method in this class will invoked by the JUnit
* framework.
*/
public class DUTTest {
/**
* Stores sub test threads errors.
*/
private static List<AssertionError> errors;
/**
* sub test threads call this function with they errors.
* #param err
*/
static void handle(AssertionError err){
errors.add(err);
}
/**
* Simpler single thread test
* #throws InterruptedException
*/
#Test
public void testSingle() {
UUT dut = new UUT();
dut.push("hello");
assertEquals("set-get", "hello", dut.message);
}
/**
* Complex multi-thread test
* #throws InterruptedException
*/
#Test
public void testMulti() throws Exception {
/*
* Initialization
*/
errors = Collections.synchronizedList(new ArrayList<AssertionError>());
UUT dut = new UUT();
MyTestThread th = new MyTestThread(dut);
/*
* Tests
*/
dut.push("hello");
assertEquals("set-get", "hello", dut.message);
th.start();
dut.push("hello");
th.join();
/*
* Error handling
*/
ListIterator<AssertionError> iter = errors.listIterator(errors.size());
while (iter.hasPrevious()) {
AssertionError err = iter.previous();
err.printStackTrace();
if(iter.previousIndex() == -1){
throw err;
}
}
}
}
Here is the Thread, which can be invoked several time. Override test() method.
package mTTest;
import static org.junit.Assert.assertEquals;
/**
* This is the custom test thread class. The main test thread (which is started
* by JUnit) starts this thread.
*
*/
public class MyTestThread extends Thread {
UUT dut;
/**
* Constructor
* #param dut : should be overwritten to your custom DUT-class
*/
public MyTestThread(UUT dut) {
this.dut =dut;
}
/**
* run() method is final to prevent overriding. Override test instead.
* It just calls the test method and handle the assertion errors.
*/
#Override
public final void run() {
try{
test();
} catch (AssertionError ex){
DUTTest.handle(ex);
}
}
/**
* Write your tests here. run calls this function.
*/
void test(){
assertEquals("set-get", "This will cause an ERROR", dut.pop());
assertEquals("set-get", "hello", dut.pop());
}
}

In Java how can I validate a thrown exception with JUnit?

When writing unit tests for a Java API there may be circumstances where you want to perform more detailed validation of an exception. I.e. more than is offered by the #test annotation offered by JUnit.
For example, consider an class that should catch an exception from some other Interface, wrap that exception and throw the wrapped exception. You may want to verify:
The exact method call that throws the wrapped exception.
That the wrapper exception has the original exception as its cause.
The message of the wrapper exception.
The main point here is that you want to be perf additional validation of an exception in a unit test (not a debate about whether you should verify things like the exception message).
What's a good approach for this?
In JUnit 4 it can be easily done using ExpectedException rule.
Here is example from javadocs:
// These tests all pass.
public static class HasExpectedException {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void throwsNothing() {
// no exception expected, none thrown: passes.
}
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
#Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
thrown.expectMessage(startsWith("What"));
throw new NullPointerException("What happened?");
}
}
As provided in your answer, it's a good approach. In addition to this:
You could wrap the function expectException into a new Annotation, called ExpectedException.
An annotated method would look like this:
#Test
#ExpectedException(class=WrapperException.class, message="Exception Message", causeException)
public void testAnExceptionWrappingFunction() {
//whatever you test
}
This way would be more readable, but it's exactly the same approach.
Another reason is: I like Annotations :)
Looking at the proposed answers, you can really feel the pain of not having closures in Java. IMHO, the most readable solution is ye good old try catch.
#Test
public void test() {
...
...
try {
...
fail("No exception caught :(");
}
catch (RuntimeException ex) {
assertEquals(Whatever.class, ex.getCause().getClass());
assertEquals("Message", ex.getMessage());
}
}
For JUNIT 3.x
public void test(){
boolean thrown = false;
try{
mightThrowEx();
} catch ( Surprise expected ){
thrown = true;
assertEquals( "message", expected.getMessage());
}
assertTrue(thrown );
}
Until this post I've done my exception validation by doing this:
try {
myObject.doThings();
fail("Should've thrown SomeException!");
} catch (SomeException e) {
assertEquals("something", e.getSomething());
}
I spent a few moments thinking about the issue though and came up with the following (Java5, JUnit 3.x):
// Functor interface for exception assertion.
public interface AssertionContainer<T extends Throwable> {
void invoke() throws T;
void validate(T throwable);
Class<T> getType();
}
// Actual assertion method.
public <T extends Throwable> void assertThrowsException(AssertionContainer<T> functor) {
try {
functor.invoke();
fail("Should've thrown "+functor.getType()+"!");
} catch (Throwable exc) {
assertSame("Thrown exception was of the wrong type! Expected "+functor.getClass()+", actual "+exc.getType(),
exc.getClass(), functor.getType());
functor.validate((T) exc);
}
}
// Example implementation for servlet I used to actually test this. It was an inner class, actually.
AssertionContainer<ServletException> functor = new AssertionContainer<ServletException>() {
public void invoke() throws ServletException {
servlet.getRequiredParameter(request, "some_param");
}
public void validate(ServletException e) {
assertEquals("Parameter \"some_param\" wasn't found!", e.getMessage());
}
public Class<ServletException> getType() {
return ServletException.class;
}
}
// And this is how it's used.
assertThrowsException(functor);
Looking at these two I can't decide which one I like more. I guess this is one of those issues where achieving a goal (in my case, the assertion method with functor parameter) isn't worth it in the long run since it's just a lot easier to do those 6+ of code to assert the try..catch block.
Then again, maybe my 10 minute result of problem solving at friday evening just isn't the most intelligent way to do this.
#akuhn:
Even without closures we can get a more readable solution (using catch-exception):
import static com.googlecode.catchexception.CatchException.*;
public void test() {
...
...
catchException(nastyBoy).doNastyStuff();
assertTrue(caughtException() instanceof WhateverException);
assertEquals("Message", caughtException().getMessage());
}
The following helper method (adapted from this blog post) does the trick:
/**
* Run a test body expecting an exception of the
* given class and with the given message.
*
* #param test To be executed and is expected to throw the exception.
* #param expectedException The type of the expected exception.
* #param expectedMessage If not null, should be the message of the expected exception.
* #param expectedCause If not null, should be the same as the cause of the received exception.
*/
public static void expectException(
Runnable test,
Class<? extends Throwable> expectedException,
String expectedMessage,
Throwable expectedCause) {
try {
test.run();
}
catch (Exception ex) {
assertSame(expectedException, ex.getClass());
if (expectedMessage != null) {
assertEquals(expectedMessage, ex.getMessage());
}
if (expectedCause != null) {
assertSame(expectedCause, ex.getCause());
}
return;
}
fail("Didn't find expected exception of type " + expectedException.getName());
}
The test code can then invoke this as follows:
TestHelper.expectException(
new Runnable() {
public void run() {
classInstanceBeingTested.methodThatThrows();
}
},
WrapperException.class,
"Exception Message",
causeException
);
i did something very simple
testBla(){
try {
someFailingMethod()
fail(); //method provided by junit
} catch(Exception e) {
//do nothing
}
}
For JUnit 5 it is much easier:
#Test
void testAppleIsSweetAndRed() throws Exception {
IllegalArgumentException ex = assertThrows(
IllegalArgumentException.class,
() -> testClass.appleIsSweetAndRed("orange", "red", "sweet"));
assertEquals("this is the exception message", ex.getMessage());
assertEquals(NullPointerException.class, ex.getCause().getClass());
}
By returning the exception object itself, assertThrows() allows you to test every aspect regarding your thrown exceptions.
I made a helper similar to the other posted ones:
public class ExpectExceptionsExecutor {
private ExpectExceptionsExecutor() {
}
public static void execute(ExpectExceptionsTemplate e) {
Class<? extends Throwable> aClass = e.getExpectedException();
try {
Method method = ExpectExceptionsTemplate.class.getMethod("doInttemplate");
method.invoke(e);
} catch (NoSuchMethodException e1) {
throw new RuntimeException();
} catch (InvocationTargetException e1) {
Throwable throwable = e1.getTargetException();
if (!aClass.isAssignableFrom(throwable.getClass())) {
// assert false
fail("Exception isn't the one expected");
} else {
assertTrue("Exception captured ", true);
return;
}
;
} catch (IllegalAccessException e1) {
throw new RuntimeException();
}
fail("No exception has been thrown");
}
}
And the template the client should implement
public interface ExpectExceptionsTemplate<T extends Throwable> {
/**
* Specify the type of exception that doInttemplate is expected to throw
* #return
*/
Class<T> getExpectedException();
/**
* Execute risky code inside this method
* TODO specify expected exception using an annotation
*/
public void doInttemplate();
}
And the client code would be something like this:
#Test
public void myTest() throws Exception {
ExpectExceptionsExecutor.execute(new ExpectExceptionsTemplate() {
#Override
public Class getExpectedException() {
return IllegalArgumentException.class;
}
#Override
public void doInttemplate() {
riskyMethod.doSomething(null);
}
});
}
It looks really verbose but if you use an IDE with good autocompletion you will only need to write the type of exception and the actual code under test. (the rest will be done by the IDE :D)

Categories