Java Reflect newInstance() causing a ConcurrentModificationException (CME) resulting in a crash - java

To sum up my project I'm trying to make an event processor that runs methods from a given list of methods. In order to invoke these methods I need to pass in the newInstance of the method. The method is correctly run, however, right after the whole program crashes with a "ConcurrentModificationException".
#EventHandler
private Listener<EventKeyInput> eventKeyInput = new Listener<>(event ->
{
for(Method m : event.getMethods())
{
try {
m.invoke(m.getDeclaringClass().newInstance(), event);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
One of the methods I wish to call
#EventAnnotation()
public void eventKeyInputeTest(EventKeyInput event)
{
System.out.println("EventKeyInput test!");
}
Please let me know if I need to provide anymore code. Thank you for any help!
Edit: Added the class where I change the method
Is there any other way to go about this?
for(Method m : listenable.getClass().getMethods())
{
if(m.isAnnotationPresent(EventAnnotation.class))
{
Parameter[] params = m.getParameters();
if(params.length != 1)
{
System.out.println("You need 1 event paramter!");
}
Class<?> eventType= params[0].getType();
try {
Object methods = eventType.getMethod("getMethods").invoke(eventType.newInstance(), null);
Method add = List.class.getDeclaredMethod("add", Object.class);
add.invoke(methods, m);
eventType.getMethod("setMethods", ArrayList.class).invoke(eventType.newInstance(), methods);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

Related

java.lang.NoSuchMethodException error but method does exist

I know there is, like, over 5 questions that ask this but mine is different. I am trying to get all classes in a package and run the tick function. Here is what one of my classes look like:
package com.stupidrepo.mydirectory.yayay;
public class test {
public void tick(MinecraftClient client) {
System.out.println(client.player.getName());
}
}
Here is how I am attempting to call this function:
ScanResult scanResult = new ClassGraph().acceptPackages("com.stupidrepo.mydirectory.yayay").enableClassInfo().scan();
private void doIt(MinecraftClient client) {
scanResult.getAllClasses().forEach((classInfo -> {
// System.out.println(classInfo.getName());
try {
classInfo.loadClass().getMethod("tick", MinecraftClient.class).invoke(null, client);
} catch (Exception e) {
e.printStackTrace();
}
}));
}
When I call the doIt function, it keeps giving me the java.lang.NoSuchMethodException error. When I print classInfo.getMethods();, it shows me [public void com.stupidrepo.mydirectory.yayay.test.tick(net.minecraft.client.MinecraftClient)].
So the method is there but java says it isn't. Please help! (By the way the code is for a Fabric MC mod)
The method tick is not static. But, when you are invoking method, you are not giving instance (but null), so it try to run the method as static. Such as It's not static, it failed.
To fix it, you can:
Set your method as static, for example:
package com.stupidrepo.mydirectory.yayay;
public class test {
public static void tick(MinecraftClient client) {
System.out.println(client.player.getName());
}
}
Create a new instance like that:
try {
Class<?> clzz = classInfo.loadClass(); // get class
Object obj = clzz.getConstructor().newInstance(); // create instance
clzz.getMethod("tick", MinecraftClient.class).invoke(obj, client); // get and call method
} catch (Exception e) {
e.printStackTrace();
}

Execute same piece of code in catch clause for all methods in a class

I have a class that has many methods. All the methods throw one exception when data is not ready. In that case, I want to retry the method after a certain interval. So in catch, I need to add retry logic. The same logic i need to add for all methods.
Is there some way/pattern to execute same logic for all catch clause without copy paste
One way I could think of is to write my own Exception class and Throw that exception. And do this retry logic from My Exception class.
Is there any other better way to this?
class MyClass {
public void method1() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method3() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
}
EDIT:
class MyClass {
public void method1(int a, int b) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {a,b};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
Object args[] = null;
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method3(String abcd, int a) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {abcd,a};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public boolean executeLater(String methodName, Object args[]){
//Execute given method with the supplied args
return true;
}
}
Added code that shows what i would be doing in each catch clause
boolean processCompleted=false;
while(!processCompleted){
try{
doProcess();
processCompleted=true;
}catch(Exception e){
Thread.sleep(10000);
}
}
This might give you an idea. It keeps try to call doProcess until it doesn't throw exception. If any exception occurs, waits 10 seconds.
Well, you could extract the whole catch block content to a method and call that one, but this only works if your retry logic is not dependent on the specific method. And it also requires a try-catch in every method.
Instead, use functional programming to shorten it:
public class Playground
{
public static void main(String[] args)
{
new Playground().method2(1, 2);
new Playground().method1();
}
public void method1()
{
tryAndTryAgain(() -> {
// logic 1
System.out.println("no params");
throw new RuntimeException();
});
}
public void method2(int a, int b)
{
tryAndTryAgain(() -> {
// logic 2
System.out.println(a + " " + b);
throw new RuntimeException();
});
}
public static void tryAndTryAgain(Runnable tryThis)
{
try
{
tryThis.run();
}
catch (Exception e)
{
new Timer().schedule(new TimerTask()
{
#Override
public void run()
{
tryAndTryAgain(tryThis);
}
}, 1000);
// existing exception handling logic
}
}
}
The exact structure depends on your specfic implementation, but it should give you an idea how to structure it. The benefit is that all those methods can concentrate on the business logic, and the retry logic and exception handling are done in a util method. And that util method doesn't even need to know anything about parameters, methods, or anything, because all the business logic is contained in the Runnable.

Calling a method with in run method for multi threading in java

I am trying to consume data from a blocked queue .The consume method needs to be implemented in the run method.
I have following code which needs to implemented in run method
#Override
public String consume(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker) throws StageException {
long nextSourceOffset = 0;
if (lastSourceOffset != null) {
nextSourceOffset = Long.parseLong(lastSourceOffset);
}
if (queue.size() != 0) {
Record record = getContext().createRecord("some-id::" + nextSourceOffset);
Map<String, Field> map = new HashMap<>();
try {
map.put("fieldName", Field.create(queue.take()));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
record.set(Field.create(map));
batchMaker.addRecord(record);
++nextSourceOffset;
}
return String.valueOf(nextSourceOffset);
}
I am trying to make the above method to run in below "Run method"
#Override
public void run() {
// TODO Auto-generated method stub
}
Is there any way i can call it.
You can just make a class constructor that takes in the parameters like so:
public class ConsumeRunner implements Runnable{
String lastSourceOffset;
int maxBatchSize;
BatchMaker batchMaker;
public ConsumeRunner(String lastSourceOffset, int maxBatchSize, BatchMaker batchMaker)
{
this.lastSourceOffset=lastSourceOffset;
this.maxBatchSize=maxBatchSize;
this.batchMaker=batchMaker;
}
#Override
public void run() {
consume(lastSourceOffset, maxBatchSize, batchMaker);
}
}
You construct your thread normally, except instead of the no-args constructor, you use the new custom one. Otherwise running it is the same.

How to get exception details and method returned value from method

how to get method return value isFailed along with exception details if method is failed
class sample
{
booelan isFailed=false;
boolean m1()
{
try{
logic of method
}
catch(Exception e)
{
String cause=e.getMessage();
isFailed=true;
}
return isFailed;
}
}
If the calling method needs to know about the Exception, just let it go through.
m1 doesn't have to return a boolean, it either worked or threw an Exception, so the calling method will know whether it is a success or not.
In this example, the calling method (m1Caller) is in the same class for simplicity .
class sample {
boolean isFailed = false;
void m1() throws Exception {
// logic of method
}
void m1Caller() {
try {
m1();
} catch (Exception e) {
// do whatever you want with the Exception's message
System.out.println(e.getMessage());
isFailed = true;
}
}
}

How To Check If A Method Exists At Runtime In Java?

How would one go about checking to see if a method exists for a class in Java? Would a try {...} catch {...} statement be good practice?
I assume that you want to check the method doSomething(String, Object).
You might try this:
boolean methodExists = false;
try {
obj.doSomething("", null);
methodExists = true;
} catch (NoSuchMethodError e) {
// ignore
}
This will not work, since the method will be resolved at compile-time.
You really need to use reflection for it. And if you have access to the source code of the method you want to call, it's even better to create an interface with the method you want to call.
[Update] The additional information is: There is an interface that may exist in two versions, an old one (without the wanted method) and a new one (with the wanted method). Based on that, I suggest the following:
package so7058621;
import java.lang.reflect.Method;
public class NetherHelper {
private static final Method getAllowedNether;
static {
Method m = null;
try {
m = World.class.getMethod("getAllowedNether");
} catch (Exception e) {
// doesn't matter
}
getAllowedNether = m;
}
/* Call this method instead from your code. */
public static boolean getAllowedNether(World world) {
if (getAllowedNether != null) {
try {
return ((Boolean) getAllowedNether.invoke(world)).booleanValue();
} catch (Exception e) {
// doesn't matter
}
}
return false;
}
interface World {
//boolean getAllowedNether();
}
public static void main(String[] args) {
System.out.println(getAllowedNether(new World() {
public boolean getAllowedNether() {
return true;
}
}));
}
}
This code tests whether the method getAllowedNether exists in the interface, so it doesn't matter whether the actual objects have the method or not.
If the method getAllowedNether must be called very often and you run into performance problems because of that, I will have to think of a more advanced answer. This one should be fine for now.
Reflection API throws NoSuchMethodException when using Class.getMethod(...) functions.
Otherwise Oracle has a nice tutorial about reflection http://download.oracle.com/javase/tutorial/reflect/index.html
In java this is called reflection. The API allows you to discover methods and call them at runtime. Here is a pointer to the docs. It's pretty verbose syntax but it'll get the job done:
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
I would use a separate method to handle the exception and have a null check to check if method exists
Ex : if (null != getDeclaredMethod(obj, "getId", null)) do your stuff...
private Method getDeclaredMethod(Object obj, String name, Class<?>... parameterTypes) {
// TODO Auto-generated method stub
try {
return obj.getClass().getDeclaredMethod(name, parameterTypes);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
If you're using Spring in your project you may check ReflectionUtil.findMethod(..). It returns null if method does not exist or does not match your requirements. Documentation.
Roland Illig is correct, but wanted to add in an example of how to check if a method exists that requires a parameter using Class.getMethod. Can also use Class.getDeclaredMethod if you are trying to access a private method.
class World {
public void star(String str) {}
private void mars(String str) {}
}
try {
World.class.getMethod("star", String.class);
World.class.getDeclaredMethod("mars", String.class);
} catch (Exception e) {}
Other solution:
public static <O> boolean existsMethod(final String methodName, final O o) {
return Stream.of(o.getClass().getMethods()).map(Method::getName).anyMatch(methodName::equals);
}

Categories