I have been trying to store one of my classes(loaded using reflection) in an object using java.lang's newInstace() method. It seems to work within the method I create the newInstace() in, however outside it, the var throws a null pointer exception... Really makes no sense to me, does anyone know how to fix this?
Class:
public class ScriptManager {
public static Class currentScript;
public static Object ScriptInstance;
public static int State;
// 0 = Not Running
// 1 = Running
// 2 = Paused
public static void runScript() {
try {
ScriptInstance = currentScript.newInstance();
currentScript.getMethod("run").invoke(ScriptInstance);
State = 1;
MainFrame.onPause();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void pauseScript() {
try {
currentScript.getMethod("pause").invoke(ScriptInstance);
State = 2;
MainFrame.onPause();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void stopScript() {
try {
currentScript.getMethod("stop").invoke(ScriptInstance);
State = 0;
MainFrame.onStop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Error:
java.lang.NullPointerException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at Bot.ScriptManager.pauseScript(ScriptManager.java:29)
Your use of static is messing you up. Try something like this:
public class ScriptManager {
private Class currentScript;
private Object scriptInstance;
private int state;
public ScriptManager() {
try {
scriptInstance = currentScript.newInstance();
currentScript.getMethod("run").invoke(scriptInstance);
//the rest
} catch (Exception e) {
e.printStackTrace();
}
}
public void pauseScript() {
try {
currentScript.getMethod("pause").invoke(scriptInstance);
//the rest
} catch (Exception e) {
e.printStackTrace();
}
}
//the rest
}
On a side note, use lower CamelCase for your variable names.
And keep your member variables private in this scenario.
Related
I'm trying to suspend (or pause) the active thread using wait() I have implemented this in my code already but when I run the code it doesn't output anything, I think it's because when it runs it starts on "suspend" would appreciate any help solving this issue. Here is the relevant code and a link with everything just in case.
GreenhouseControls.java
public class GreenhouseControls extends Controller implements Serializable {
...
private Boolean suspend = false;
...
public void SuspendEvent() {
suspend = true;
}
public void ResumeEvent() {
suspend = false;
}
public Boolean getSuspend() {
return suspend;
}
...
}
Event.java
public abstract class Event implements Runnable {
...
private boolean suspend;
...
public synchronized void isSuspended() {
suspend = greenhouseControls.getSuspend();
notifyAll();
}
public void run() {
try {
while (suspend = true) {
try {
synchronized(this) {
wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
Thread.sleep(delayTime);
}
catch (InterruptedException e) {
e.printStackTrace();
}
try {
this.action();
}
catch (GreenhouseControls.ControllerException e) {
e.printStackTrace();
}
}
...
}
FansOff.java: there are other classes like this one each very similar to each other and they are the ones actually producing the output
public class FansOff extends Event {
...
public void run() {
try {
boolean suspend = false;
while (suspend = true) {
try {
synchronized(this) {
wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
Thread.sleep(delayTime);
}
catch (InterruptedException e) {
e.printStackTrace();
}
try {
this.action();
System.out.println(this.toString());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Full code: here.
Thanks in advance.
So i am making a game with Java right now as an exercise and i save a Treemap with Levels in it with Jackson. The Levels arent big and i dont want loading times between Levels, just between whole worlds. So here i come to my problem: The Treemap is defined that way:
private TreeMap<Integer, Level> levelList;
so everytime i load in a World in the Editor. Thats why i reset the selectedLevel to 0:
private void loadWorld() {
selectedLevel = 0;
levelList = LevelManager.loadWorld(saveLocations.getLocations().get((selectedWorld)));
loadLevel();
}
(saveLocations is a class that converts the selectedWorld int to a String of the directoy of the World)
and then load in the Level in particular:
private void loadLevel() {
level = levelList.get(Integer.valueOf(selectedLevel));
levelTiles.clear();
try {
levelTiles.addAll(level.getLevelProps());
} catch (Exception e) {
resetBuilder();
}
try {
levelTiles.add(
new GroundTile(level.getSpawn().getX(), level.getSpawn().getY(), 15, 15,EntityState.SPAWNER, 1));
} catch (Exception e) {
}
}
i get the following exception:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at java.lang.Integer.compareTo(Unknown Source)
at java.util.TreeMap.getEntry(Unknown Source)
at java.util.TreeMap.get(Unknown Source)
at logicProgramm.Editor.loadLevel(Editor.java:258)
at logicProgramm.Editor.loadWorld(Editor.java:277)
Can someone help me with this problem?
This is btw my Levelmanager class:
public class LevelManager {
public static void writeJsonWorld(TreeMap<Integer, Level> World, String name) {
System.out.println("Saver");
ObjectMapper mapper = new ObjectMapper();
try {
mapper.writeValue(Paths.get("Worlds/" + name).toFile(), World);
} catch (IOException e) {
System.out.println("Save Failed");
e.printStackTrace();
}
System.out.println(name + " with level: " + World.size());
System.out.println("Save complete");
}
public static TreeMap<Integer, Level> loadWorld(String name) {
System.out.println("Loader");
TreeMap<Integer, Level> levelList = new TreeMap<>();
try {
ObjectMapper mapper = new ObjectMapper();
levelList = mapper.readValue(Paths.get("Worlds/" + name).toFile(), TreeMap.class);
} catch (IOException e) {
levelList = new TreeMap<>();
} catch (NullPointerException e) {
e.printStackTrace();
}
return levelList;
}
}
class A {
static int a = 1 / 0;
}
In this code when we load the class, it will throw an exception because of arithmetic exception. How can I catch that exception?
use this code.
static int a=0;
try{
a = 1/0;
}catch(Exception e){
e.printStackTrace();
}
using static block
public class A {
private static int a;
static {
try {
a = 1 / 0;
} catch (Exception e) {
System.out.print("error");
}
}
}
Make it in static block.
static {
try {
Integer a = 1 / 0;
} catch (Exception e) {
}
}
I happen to have a problem with some attempts at reading the same variable in socket multi-threading, not being able to share it among threads.
It works as an app where an employer assigns work to an employee. Through his interface the employer can add and assignment to an ArrayList inside a class named ListadoPedidos.
When the employer's ServerSocket accepts an employee Socket, it starts a TCP connection and launches the following thread:
public class HiloServer implements Runnable{
private ListadoPedidos peds=new ListadoPedidos();
private ListadoOperarios operarios=new ListadoOperarios();
private ListadoSockets sockets=new ListadoSockets();
private SocketServer s;
public HiloServer(SocketServer sock, JFrame frame, ListadoPedidos pedidos) {
s=sock;
peds=pedidos;
}
/* (non-Javadoc)
* #see java.lang.Runnable#run()
*/
#Override
public void run() {
boolean agregar;
Socket nuevo;
try {
while(true) {
// ACEPTA OPERARIOS QUE DESEEN CONECTARSE
s.aceptar();
nuevo=s.getSocket();
sockets.addSocket(nuevo);
new NuevoCliente();
HiloDatos hd=new HiloDatos(s, nuevo,operarios,peds,sockets);
Thread t=new Thread(hd);
t.start();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
*note that I send the object where the assigments added are stored.
Then it starts another thread that will work as a sort of "validation" for a number the employee's have to insert and send through his Swing interface to truly enter the system. This thread is generated everytime a new socket employee makes a TCP connection to the ServerSocket employer. It goes like:
public class HiloDatos implements Runnable {
private int n;
private Socket cliente;
private SocketServer server;
private int opRecibido;
private ListadoOperarios ops;
private ListadoPedidos peds;
private ListadoSockets socks;
public HiloDatos(SocketServer ss, Socket nuevo, ListadoOperarios operarios, ListadoPedidos pedidos, ListadoSockets sockets) {
cliente=nuevo;
server=ss;
ops=operarios;
peds=pedidos;
socks=sockets;
}
#Override
public void run() {
server.setSocket(cliente);
boolean agregar, aceptado=false;
try {
do {
// RECIBE EL NRO OPERARIO Y VERIFICA SU EXISTENCIA
agregar=true;
opRecibido=Integer.parseInt(server.recibir());
for(int c=0;c<ops.getOperarios().size();c++) {
if (opRecibido==ops.getOperarios().get(c)) {
new ErrorRepetido();
agregar=false;break;
}
}
if (agregar==true) {
ops.addOperarios(opRecibido);
server.enviar("Si");
aceptado=true;
}
}while(aceptado==false);
HiloPedidos hp=new HiloPedidos(server,opRecibido,ops,peds,socks);
Thread t=new Thread(hp);
t.start();
}catch (NumberFormatException e) {
new ErrorDatos();
} catch (ConnectException e) {
new ErrorConexion();
} catch (SocketException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(cliente));
cliente.close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnSocket();
} catch (IOException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(cliente));
cliente.close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnFlujo();
}
}
}
And lastly it launches yet another Thread that looks for that same validation number from the thread above in the ArrayList of assignments ("pedidos" of class ListadoPedidos) i kept passing from thread to thread, and if it finds a "new" one, it should send it to the connected socket:
public class HiloPedidos implements Runnable {
private Pedido ped;
private SocketServer server;
private int op;
private ListadoOperarios ops;
private ListadoPedidos peds;
private ListadoSockets socks;
public HiloPedidos(SocketServer ss, int opRecibido, ListadoOperarios operarios, ListadoPedidos pedidos, ListadoSockets sockets) {
server=ss;
opRecibido=op;
ops=operarios;
peds=pedidos;
socks=sockets;
}
#Override
public void run() {
int cambio=0, nuevo;
Pedido pedRecibido;
try {
while(true) {
// ENVÍA PEDIDOS
nuevo=peds.Contar(op);
if(nuevo==cambio) {
cambio=peds.Contar(op);
pedRecibido=peds.TraerNuevo(op, cambio);
server.enviarObjeto(pedRecibido);
}
}}
catch (NumberFormatException e) {
new ErrorDatos();
} catch (ConnectException e) {
new ErrorConexion();
} catch (SocketException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(server.getSocket()));
server.getSocket().close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnSocket();
} catch (IOException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(server.getSocket()));
server.getSocket().close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnFlujo();
}
}
}
Problem is that the last thread can't really notice a change in the list, as i debugged it and never reached the breakpoint inside the condition of sending the assignment. The class ListadoPedidos goes like this:
public class ListadoPedidos {
private static volatile ArrayList<Pedido> pedidos=new ArrayList<>();
public ListadoPedidos() {
}
public ArrayList<Pedido> getPedidos() {
return pedidos;
}
public synchronized void addPedidos(Pedido pedido) {
pedidos.add(pedido);
}
public int Contar(int o) {
int n=0;
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
}
return n;
}
public Pedido TraerNuevo(int o, int c) {
int n=0;
Pedido nuevo = new Pedido();
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
if (n==c) {
nuevo=p;break;
}
}
return nuevo;
}
}
Contar is the one that counts for an assignment with the value nrooperario same as the value it brings from the thread, and TraerNuevo brings the assignment to be sended (never reached this method).
I tried declaring the ArrayList as volatile and all but nothing works. Mind that even if i use socket connections, the problem has more to do with shared varaible not being able to update between threads. Any help will be appreciated.
Try this, basically, synchronize access.
public class ListadoPedidos {
private static volatile ArrayList<Pedido> pedidos=new ArrayList<>();
public ListadoPedidos() {
}
/**
* Here DO NOT return the arrayList. The underlying implementation is not threadsafe
*/
// public ArrayList<Pedido> getPedidos() {
// return pedidos;
// }
public synchronized void addPedidos(Pedido pedido) {
pedidos.add(pedido);
}
public synchronized int Contar(int o) {
int n=0;
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
}
return n;
}
public synchronized Pedido TraerNuevo(int o, int c) {
int n=0;
Pedido nuevo = new Pedido();
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
if (n==c) {
nuevo=p;break;
}
}
return nuevo;
}
}
The amount of code you have given us makes it difficult to answer your question. To be honest, the Spanish does not help either. But I can give you some general advice.
Let us start with the question. What exactly is the question? From what I can understand, it comes down to: "how can two threads read the same variable?"
Even if that is not the question, try to make the question as clear as possible for yourself.
Then start with a new test-project separate from the project you are working on. Write the minimal amount of code that you think should work. If it does not work, write even less code that does work (e.g. use static variables to make things even more simple). Go back and forth until you have code that can answer your question. If you cannot get it to work, step back and think about assumptions that you made that might not be true.
If you still cannot figure it out, come back here with the minimal amount of code that you think should work and a clear question.
This method of "trying it with minimal code in a test-project" is something I still use after years of programming to solve problems. When I solve a problem this way, I usually learn something new and often I discover that I made an assumption that did not hold true.
let's say i have 3 classes:
1. Storage which contains just one integer.
2. Counter which contains a thread inside who's responsible for counting (0,1,..,k) and stores each iteration of the loop index in Storage class.
3.Printer which contains a thread who's responsible for reading the value in class Storage and print it.
now i have to create a main class which creates these 3 objects runs the threads of Counter and Printer , and everynumber from(0,1,..,k) has to be printed just once and in the right order.
how do i synchronize the access to my Storage class so first i put a number inside Storage with Counter ,than print it with my Printer class ?
here's what i've wrote so far:
public class Storage {
private int num;
public Storage(){
}
public synchronized void setNum(int num){
this.num = num;
}
public synchronized int getNum(){
return num;
}
public class Counter implements Runnable {
Storage s;
public Counter(Storage t){
s = t;
}
#Override
public void run() {
int i = 0;
while(true){
s.setNum(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Printer implements Runnable {
Storage s;
public Printer(Storage s){
this.s= s;
}
#Override
public void run() {
while(true){
System.out.println(s.getNum());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class mainProg {
public static void main(String[] args){
Storage s = new Storage();
Counter c = new Counter(s);
Printer p = new Printer(s);
Thread c1 = new Thread(c);
Thread p2 = new Thread(p);
c1.start();
p2.start();
}
}
EDIT: i found out a solution, here it is:
public class Storage {
private int num;
private boolean available = false;
public Storage(){
}
public synchronized void setNum(int num){
while(available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = true;
notifyAll();
this.num = num;
}
public synchronized int getNum(){
while(!available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = false;
notifyAll();
return num;
}
}
This approach won't work, because it's not guaranteed that for every cycle of Counter a cycle of Printer will be executed in a parallel thread. You need to be able to store more than a one value in your Storage.
You can use BlockingQueue here and rewrite your Storage class like this:
public class Storage {
private BlockingQueue<Integer> numbers = new LinkedBlockingQueue<Integer>();
public void setNum(int num) {
try {
this.numbers.put(num);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public int getNum() {
try {
return numbers.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Note that if BlockingQueue is empty and Printer wants to get a new value, it will wait while a new element occurrs in the queue.