My problem is simple: I need to access variable history (which is declared in class BinaryServer) from another class.I'm using more classes to run this code.It's just simple client and server made of sockets.Client sends to server binary code/text and server translates it to text/binary code and sends it back to client.I can provide all classes if needed.
BinaryServer class
import java.net.*;
import java.util.ArrayList;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import graphics.gui;
public class BinaryServer extends gui implements ActionListener,Runnable
{
private ServerSocket server;
private Socket client;
public String text;
private BufferedReader reader;
public static ArrayList<String> history;
public static String binary_letter;
public static String[] letter;
public static int i;
public static String[] binary;
public static String sendback;
public static void main(String[] args)throws IOException
{
BinaryServer instance=new BinaryServer();
gui.buildframe(310,360,"Binary translator server");
gui.buildpane(300,300,true);
gui.buildbutton(300,20,"Translate");
instance.server(63400);
}
public void server(int port)throws IOException
{
history=new ArrayList<String>(100);
server=new ServerSocket(port);
button.addActionListener(this);
while(true)
{
client=server.accept();
reader=new BufferedReader(new InputStreamReader(client.getInputStream()));
text=reader.readLine();
history.add(text);
message.setText(message.getText()+"\n"+text+": ");
}
}
#Override
public void actionPerformed(ActionEvent e)
{
Thread response=new Thread(new BinaryServer());
if(text.contains("0"))
{
int length=text.length();
letter=new String[length+1];
sendback="";
int begin=-8;
int end=0;
for(i=1;i<=length/8;i++)
{
begin=begin+8;
end=i*8;
binary_letter=text.substring(begin,end);
Libary.translate();
message.setText(message.getText()+letter[i]);
sendback=sendback+letter[0+i];
}
}
else
{
int length=text.length();
letter=new String[length+1];
binary=new String[length+1];
sendback="";
for(i=1;i<=length;i++)
{
letter[i]=text.substring(i-1,i);
Libary.encode();
message.setText(message.getText()+binary[i]);
sendback=sendback+binary[0+i];
}
}
response.start();
}
public void run()
{
try
{
Socket feedback=new Socket("localhost",63403);
PrintWriter writer=new PrintWriter(feedback.getOutputStream(),true);
writer.println(sendback);
feedback.close();
return;
}
catch(IOException exc)
{
System.out.println("");
}
}
}
BinaryHistory class (The one I want access variable from)
public class BinaryHistory
{
public static void main(String[] args)
{
show();
}
public static void show()
{
System.out.println(BinaryServer.history);
}
When I access variable history from class BinaryHistory, it's alway null.
If you only declare the variable, regardless of the type or whether or not it's static, it will get a default value of null.
You have to initialize the variable too:
public static ArrayList<String> history = new ArrayList<>();
Related
I am trying to use Soot to perform data flow analysis on a java file which is called Example.java.
Here is my Example.java file, my goal is to know which saySomething method animal.saySomething() will call. Here is the code for Example.java I am using:
package a1;
public class Example {
static Animal neverCalled() {
return new Fish();
}
static Animal selectAnimal() {
return new Cat();
}
public static void main(String[] args) {
Animal animal = selectAnimal();
animal.saySomething();
}
}
abstract class Animal {
public abstract void saySomething();
}
class Cat extends Animal {
public void saySomething() {
System.out.println("purr");
}
}
class Dog extends Animal {
public void saySomething() {
System.out.println("woof");
}
}
class Fish extends Animal {
public void saySomething() {
System.out.println("...");
}
}
class Car { // not an Animal
public void saySomething() {
System.out.println("honk!");
}
}
and here is the code I am using to analyze Example.java using Soot, this code is located in the file: TestSootCallGraph.java which follows here:
package a1;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import soot.*;
import soot.jimple.Stmt;
import soot.jimple.spark.SparkTransformer;
import soot.jimple.toolkits.callgraph.CHATransformer;
import soot.jimple.toolkits.callgraph.CallGraph;
import soot.jimple.toolkits.callgraph.Targets;
import soot.options.Options;
public class TestSootCallGraph extends SceneTransformer {
static LinkedList<String> excludeList;
public static void main(String[] args) {
String mainclass = "Example";
// //set classpath
String javapath = System.getProperty("java.class.path");
String jredir = System.getProperty("java.home")+"/lib/rt.jar";
String path = javapath+File.pathSeparator+jredir;
Scene.v().setSootClassPath(path);
//add an intra-procedural analysis phase to Soot
TestSootCallGraph analysis = new TestSootCallGraph();
PackManager.v().getPack("wjtp").add(new Transform("wjtp.TestSootCallGraph", analysis));
excludeJDKLibrary();
//whole program analysis
Options.v().set_whole_program(true);
//load and set main class
Options.v().set_app(true);
SootClass appclass = Scene.v().loadClassAndSupport(mainclass);
System.out.println(appclass);
Scene.v().setMainClass(appclass);
Scene.v().loadNecessaryClasses();
//enable call graph
//enableCHACallGraph();
//enableSparkCallGraph();
//start working
PackManager.v().runPacks();
}
private static void excludeJDKLibrary()
{
//exclude jdk classes
Options.v().set_exclude(excludeList());
//this option must be disabled for a sound call graph
Options.v().set_no_bodies_for_excluded(true);
Options.v().set_allow_phantom_refs(true);
}
private static void enableSparkCallGraph() {
//Enable Spark
HashMap<String,String> opt = new HashMap<String,String>();
//opt.put("propagator","worklist");
//opt.put("simple-edges-bidirectional","false");
opt.put("on-fly-cg","true");
//opt.put("set-impl","double");
//opt.put("double-set-old","hybrid");
//opt.put("double-set-new","hybrid");
//opt.put("pre_jimplify", "true");
SparkTransformer.v().transform("",opt);
PhaseOptions.v().setPhaseOption("cg.spark", "enabled:true");
}
private static void enableCHACallGraph() {
CHATransformer.v().transform();
}
private static LinkedList<String> excludeList()
{
if(excludeList==null)
{
excludeList = new LinkedList<String> ();
excludeList.add("java.");
excludeList.add("javax.");
excludeList.add("sun.");
excludeList.add("sunw.");
excludeList.add("com.sun.");
excludeList.add("com.ibm.");
excludeList.add("com.apple.");
excludeList.add("apple.awt.");
}
return excludeList;
}
#Override
protected void internalTransform(String phaseName,
Map options) {
int numOfEdges =0;
CallGraph callGraph = Scene.v().getCallGraph();
for(SootClass sc : Scene.v().getApplicationClasses()){
for(SootMethod m : sc.getMethods()){
Iterator<MethodOrMethodContext> targets = new Targets(
callGraph.edgesOutOf(m));
while (targets.hasNext()) {
numOfEdges++;
SootMethod tgt = (SootMethod) targets.next();
System.out.println(m + " may call " + tgt);
}
}
}
System.err.println("Total Edges:" + numOfEdges);
}
}
I receive the following error when executing TestSootCallGraph.java which aims at analyzing Example.java. How can I fix this?
Example
Exception in thread "main" java.lang.RuntimeException: Main-class has no main method!
at soot.Scene.setMainClass(Scene.java:171)
at a1.TestSootCallGraph.main(TestSootCallGraph.java:47)
package RMI_Package;
import java.rmi.server.*;
import java.rmi.*;
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
public String sayHello(){
return "Server says,'Hey'";
}
public MyRemoteImpl() throws RemoteException{}
public static void main(String [] args){
try{
MyRemote service = new MyRemoteImpl();
Naming.rebind("Remote Hello",service);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
This code is from Head First Java Book when i run it, it throws the java.net.MalformedURLException.
As specified by the Naming documentation, the first parameter of bind should be a valid URL.
As an example (taken from here):
Naming.bind("rmi://localhost:8800/YourObject", service);
A reproducible example:
package test;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
public class mySerializable implements Serializable {
private static int f;
private static int g;
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("f", Integer.class),
new ObjectStreamField("g", Integer.class),
};
public static void main(String[] args) {
save();
}
public static void save() {
try {
FileOutputStream fileOut = new FileOutputStream("config" + ".ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(new mySerializable());
out.close();
fileOut.close();
} catch (Exception ex) {
System.out.println("save()" + ex.getLocalizedMessage()); }
}
public static int getF() {
return f;
}
public static void setF(int f) {
mySerializable.f = f;
}
public static int getG() {
return g;
}
public static void setG(int g) {
mySerializable.g = g;
}
}
The program prints:
save(): test.mySerializable; unmatched serializable field(s) declared
You've got two problems:
f and g are static; static fields aren't serialized.
They're also of type int, not Integer.
Make them non-static, and refer to them using int.class.
Ideone demo
I'm currently coding a project Java in eclipse which has two classes. The first class (open) I use to send a specific string to my second class (viewer) and then run my second class. The second class (viewer) I have imported into my program in the form of a jar file. I have done it this way as class viewer is a pdf viewer that i created using apache PDFBox and class open sends the file to the viewer to use, but the file will be different depending on many conditions (that are not relevant) in class open. The point is that class open needs to be separate from class viewer and can not simply be two different methods in one class. I would like to know if there is a way for class open to know when class viewer has been closed, as currently I am using a while loop, which just eats up memory and is very inefficient. The code I have does currently work, but I feel there is a better way, perhaps using listeners. This is the code for closing class viewer:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
//and import swing components ect
Public class viewer extends javax.swing.JFrame
implements KeyListener,
ActionListener{
private javax.swing.JButton zoomIn;
private javax.swing.JButton zoomOut;
//and a bunch more swing components
public static boolean closed = false;
public static String fileName = "";
public viewer()
{
}
private void initComponents() throws IOException
{
addWindowListener(new java.awt.event.WindowAdapter()
{
#Override
public void windowClosing(java.awt.event.WindowEvent evt)
{
exitApplication();
}
});
}
private void exitMenuItemActionPerformed(ActionEvent evt)
{
if( document != null )
{
try
{
document.close();
}
catch( IOException e )
{
throw new RuntimeException(e);
}
}
closed = true;
System.exit(0);
}
public static void main(String filename) throws Exception
{
fileName = filename;
viewer mainViewer = new viewer();
String[] splittedStr = fileName.split("/");
BASETITLE = splittedStr[splittedStr.length - 1];
if (fileName != null)
{
mainViewer.openPDFFile(fileName);
}
mainViewer.setVisible(true);
}
This is my code from class open:
public static void main(String[] args) throws Exception {
String fileName = "C:/Files/Test.pdf";
viewer.main(fileName);
while(viewer.closed == false)
{
if(viewer.closed == true)
{
System.out.print("The Viewer Has Been Closed");
}
}
}
I want to know when it is closed so I can delete the file on the local drive. Thanks for your help!
Either you pass a callback (e.g. a Runnable) as argument to viewer.main, like viewer.main(fileName, () -> System.out.print("The Viewer Has Been Closed")) and make sure that it is called when the process is done, or you do as you've done except that you sleep your main thread a short time in the while loop, like Thread.sleep(100).
okay so I actually found an answer to my question and I'll just post it in case someone else had the same problem as me. I added a interface to the open class with the method close as shown:
import mainpackage.viewer;
public class Open implements closeInterface{
public Open() { }
public static String fileName;
public static void main(String[] args) throws Exception {
fileName = "C:/Files/Test.pdf";
run();
}
#Override
public void close() {
System.out.print("The Viewer Has Been Closed");
}
public static void run() throws Exception
{
viewer view = new viewer();
view.main(fileName);
view.addListener(new Open());
}
}
This was my code for my interface:
package mainpackage;
public interface closeInterface {
public void close();
}
And this was the snipit of code for my Viewer class
public class viewer extends javax.swing.JFrame {
private static closeInterface Closed;
private void initComponents() throws IOException
{
addWindowListener(new java.awt.event.WindowAdapter()
{
#Override
public void windowClosing(java.awt.event.WindowEvent evt)
{
exitApplication();
}
});
}
private void exitApplication()
{
try
{
if( document != null )
{
document.close();
}
}
catch( IOException io )
{
//do nothing because we are closing the application
}
Closed.close();
this.setVisible( false );
this.dispose();
}
public void addListener(closeInterface closed){
Closed = closed;
}
}
Thanks for everyone's help!
Earlier I had a problem when an inner anonymous class did not see a field of the "outer" class. I needed to make a final variable to make it visible to the inner class. Now I have an opposite situation. In the "outer" class "ClientListener" I use an inner class "Thread" and the "Thread" class I have the "run" method and does see the "earPort" from the "outer" class! Why?
import java.io.IOException;
import java.net.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ClientsListener {
private int earPort;
// Constructor.
public ClientsListener(int earPort) {
this.earPort = earPort;
}
public void starListening() {
Thread inputStreamsGenerator = new Thread() {
public void run() {
System.out.println(earPort);
try {
System.out.println(earPort);
ServerSocket listeningSocket = new ServerSocket(earPort);
Socket serverSideSocket = listeningSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(serverSideSocket.getInputStream()));
} catch (IOException e) {
System.out.println("");
}
}
};
inputStreamsGenerator.start();
}
}
Anonymous inner classes have access to static and instance variables. If you want to have also access to local variables, declare them as final. This is how it works:)
Your anonymous inner class has access to the attributes of the containing object. All inner classes that are not declared static have an implicit accessor.
If you want to prevent this from happening, you can declare a static inner class and instantiate that:
public class ClientsListener {
private int earPort;
// Constructor.
public ClientsListener(int earPort) {
this.earPort = earPort;
}
public void starListening() {
Thread inputStreamsGenerator = new InputStreamsGenerator();
inputStreamsGenerator.start();
}
private static class InputStreamsGenerator extends Thread() {
public void run() {
// no access to earport in next line (can make it a constructor argument)
System.out.println(earPort);
try {
System.out.println(earPort);
ServerSocket listeningSocket = new ServerSocket(earPort);
Socket serverSideSocket = listeningSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(serverSideSocket.getInputStream()));
} catch (IOException e) {
System.out.println("");
}
}
};
}