Can you please help me with the answer, please?
I've read a lot, but can understand, how to organize the code.
I want to create my own method to work with the Network and call it time to time in a program.
But this compilation error makes me mad:
variable might be not have been initialized
I do understand why, but I can`t see solution((
My vision is to open Socket and related streams only one time and close it when needed.
public static void socket_r (String action, String ip_addr, String to_write, int port) throws IOException {
String s;
switch (action) {
case "Create": Socket socket = new Socket (ip_addr, port);
OutputStream out_from_socket = socket.getOutputStream();
PrintWriter writer_socket = new PrintWriter(out_from_socket, true);
InputStream input_socket = socket.getInputStream();
BufferedReader reader_socket = new BufferedReader(new InputStreamReader(input_socket));
break;
case "Write": writer_socket.println(to_write);
writer_socket.println();
break;
case "Read": while ((s = reader_socket.readLine()) != null) System.out.println(s);
break;
case "Close": writer_socket.println(to_write);
writer_socket.println();
writer_socket.close();
reader_socket.close();
break;
}
}
Lets start with why the code won't compile ...
The variables reader_socket and writer_socket are local variables. That means:
they must be definitely assigned before you can use them, and
they disappear ... along with their respective values ... when your socket_r method returns to the caller.
In your code, there are lots of places where reader_socket and writer_socket are used without being definitely assigned. For example:
writer_socket.println(to_write);
A call to socket_r can reach that statement without passing through any statement that assigns a value to writer_socket. (Yes. Look at it.)
But here's the problem. Your design requires that a socket_r("write", ...) call uses state that only gets initialized in a socket_r("create", ...) call. And then it gets thrown away.
Basically, you cannot implement that design using local variables for the state.
So what is the solution?
In order of "goodness"
Make the variables static variables in the enclosing class. (This is a bad solution, but it involves the least change to your existing code. Why it is bad is ... well ... read some more about OO and why static should be rarely used.)
Make the method non-static method and make the variables instance variables.
Solution 2 AND replace socket_r with a separate method for each "action".
Solution 3 AND put in some extra logic to enforce a proper "life-cycle" for the socket; i.e. create before reads and writes, no reads or writes after close, etcetera.
Basically, you need to rethink your design to do things in an OO way, and it will get a whole lot easier.
Related
Disclaimer: I work on a non-traditional project, so don't be shocked if some assumptions seem absurd.
Context
I wish to create a stream reader for integers, strings, and the other common types in Scala, but to start with I focus only on integers. Also note that I'm not interesting in handling exception at the moment -- I'll deal with them in due time and this will be reflected in the API and in the meantime I can make the huge assumption that failures won't occur..
The API should be relatively simple, but due to the nature of the project I'm working on, I can't rely on some feature of Scala and the API needs to look something like this (slightly simplified for the purpose of this question):
object FileInputStream {
def open(filename: String): FileInputStream =
new FileInputStream(
try {
// Check whether the stream can be opened or not
val out = new java.io.FileReader(filename)
out.close()
Some[String](filename)
} catch {
case _: Throwable => None[String]
}
)
}
case class FileInputStream(var filename: Option[String]) {
def close: Boolean = {
filename = None[String]
true // This implementation never fails
}
def isOpen: Boolean = filename.isDefined
def readInt: Int = nativeReadInt
private def nativeReadInt: Int = {
??? // TODO
}
}
object StdIn {
def readInt: Int = nativeReadInt
private def nativeReadInt: Int = {
??? // TODO
}
}
Please also note that I cannot rely on additional fields in this class, with the exception of Int variables. This (probably) implies that the stream has to be opened and closed for every operations. Hence, it goes without saying that the implementation will not be efficient, but this is not an issue.
The Question
My goal is to implement the two nativeReadInt methods such that the input stream gets consumed by only one integer if one is available straight away. However, if the input doesn't start (w.r.t. the last read operation) with an integer then nothing should be read and a fixed value can be returned, say -1.
I've explored several high level Java and Scala standard APIs, but none seemed to offer a way to re-open a stream to a given position trivially. My hope is to avoid implementing low level parsing based solely on java.io.InputStream and its read() and skip(n) methods.
Additionally, to let the user read from the standard input stream, I need to avoid using scala.io.StdIn.readInt() method because it reads "an entire line of the default input", therefore trashing some potential data.
Are you aware of a Java or Scala API that could do the trick here?
Thank you
This is my very first question on SO and I'm confused there isn't a similar question yet!
So the question is:
Why doesn't try-with-resources work with field variables?
Or in other words: Why do I always need a local variable for that?
Here goes some example code:
public class FileWriteTest {
public FileWriter file;
public void workingDemo() {
try(FileWriter file = new FileWriter(new File("someFilePath")) {
// do something
} catch (IOException e) {
e.printStackTrace();
}
}
public void notWorkingDemo() {
file = null;
try(file = new FileWriter(new File("someFilePath")) {
// do something
} catch (IOException e) {
e.printStackTrace();
}
}
}
May anyone explain me why there is this convention?
An instance variable may be changed at any point during the execution of the try-with-resources block. This would break its invariant and prevent the cleanup. Note that the local variable is implictly final, for the same reason.
BTW a better question is, why does Java force us to declare a local variable, even if we don't refer to it within the block. C#, for example, doesn't require this.
Update: with version 9, Java has stopped forcing us:
private final Some obj = new Some();
try (obj) {
// obj captured in a hidden local variable, resource closed in the end
}
I suspect the designers considered using a field a bad idea as this allow the object to escape the region of usage. i.e. it is only valid in the try block so you shouldn't be able to access it anywhere else.
Section 14.20.3 of the Java Language Specification states it will only work with local variables.
Why is this? My guess is checking for definite assignment and escapage (the local variable doesn't escape into the scope of another method). A field may be initialized anywhere in the class. My guess is that by validating it's a local variable, it's much simpler to analyse.
With Java 9, They added support for try with resources with variables.
// Original try-with-resources statement from JDK 7 or 8
try (Resource r1 = resource1;
Resource r2 = resource2) {
// Use of resource1 and resource 2 through r1 and r2.
}
// New and improved try-with-resources statement in JDK 9
try (resource1;
resource2) {
// Use of resource1 and resource 2.
}
https://blogs.oracle.com/darcy/more-concise-try-with-resources-statements-in-jdk-9
First off, I think it would be bad practice to have a variable/resource which is used at multiple places. If it is not opened in the try, then you cannot close it afterwards, if it is opened there, then you won't need a non-local variable.
This leads to "second": If you have a resource open already, then you need to close it somewhere else explicitly, otherwise the autoclose wouldn't know if it is open or not.
So, IMHO it makes only sense to handle it the way it is specified in the specification.
From Java 9, no need to use a local variable in try-with-resources block. See here.
It may have to do with consistency with the language specifications.
Whenever a variable is declared between two brackets, it is encapsulated inside and cannot be accessed from the outside:
anything
{
int var;
}
// cannot access var from here!
Why shoul try { } be an exception ?
My program has the following structure:
void main (String[] args) {
Object largeObject = longInitialization();
interestingLogic(largeObject);
}
The longInitialization code never changes during development. BUt whenever I change the interestingLogic, I have to run the program again and wait for the longInitialization to complete.
Unfortunately I cannot serialize largeObject because it is not Serializable and I don't have the code to it.
Is there a trick by which I can save the initialization time? Maybe, in some way save the state of the JVM just after initialization, and then always start from that state?
You can make little modification of code:
main(){
Object largeObject = longInitialization();
boolean debug = true;
while(debug){
interestingLogic(largeObject);
}
}
now run program in debug mode. Set breakpoint at interestingLogic call and use code hotswap debug mode in IDE. read more about hotswap in Eclipe: Java Hotswap with Eclipses and Remote Debugging on Local Machine
//Edit:
One more option. Just write mock of largeObject.
You will need a new object to call interestingLogic(largeObject). You can make changes to the new object while the driver program is waiting for user input.
void main (String[] args) {
Object largeObject = longInitialization();
boolean anotherTry = true;
String answer = "";
Scanner input = new Scanner(System.in);
while (anotherTry) {
Object newobject = NewObject();
newobject.interestingLogic(largeObject).
System.out.print("Run Again Y/N");
answer = input.nextLine();
if (answer.equalsIgnoreCase("N")) {
anotherTry = false;
}
}
}
If the large object is not needed immediately, you could decorate it with a "lazy initializing" wrapper, and invoke the "longInitialization" just before you want to access it.
A second solution could be "cloning" it by marshalling/unmarshalling it to an xml file
Because you said "...cannot serialize largeObject..." there is no way to persist an object across JVM lifetimes (since you don't have the source). But, you have code that initializes/uses the largeOject. Create a serializable debugLargeObject that acts like the real largeObject and use debugLargeObject during development.
Not without a lot of work. You need a minor refactor, as shown by Guido, then you need to reload the NewObject class each time through the loop (or whatever). In other words, your VM needs to be able to remove the NewObject class, then reload it, each time you change the code.
There are commercial products which do this (see JRebel, for example). You can roll your own (see this StackOverflow topic: Unloading classes in java?). You can hotswap, if you're very careful about your interestingLogic. But ultimately, you need to swap out that class somehow.
I am using java to create an application for network management. In this application I establish communication with network devices using SNMP4j library (for the snmp protocol). So, Im supposed to scan certain values of the network devices using this protocol and put the result into a file for caching. Up in some point I decided to make my application multi-threaded and assign a device to a thread. I created a class that implements the runnable interface and then scans for the values that I want for each device.
When i run this class alone it, works fine. but when I put multiple threads at the same time the output mess up, it prints additional or out of order output into the files. Now, i wonder if this problem is due to the I/O or due to the communication.
Here I'll put some of the code so that you can see what im doing and help me figure what's wrong.
public class DeviceScanner implements Runnable{
private final SNMPCommunicator comm;
private OutputStreamWriter out;
public DeviceScanner(String ip, OutputStream output) throws IOException {
this.device=ip;
this.comm = new SNMPV1Communicator(device);
oids=MIB2.ifTableHeaders;
out = new OutputStreamWriter(output);
}
#Override
public void run(){
//Here I use the communicator to request for desired data goes something like ...
String read=""
for (int j=0; j<num; j++){
read= comm.snmpGetNext(oids);
out.write(read);
this.updateHeaders(read);
}
out.flush();
//...
}
}
some of the expected ooutput would be something like:
1.3.6.1.2.1.1.1.0 = SmartSTACK ELS100-S24TX2M
1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.52.3.9.1.10.7
1.3.6.1.2.1.1.3.0 = 26 days, 22:35:02.31
1.3.6.1.2.1.1.4.0 = admin
1.3.6.1.2.1.1.5.0 = els
1.3.6.1.2.1.1.6.0 = Computer Room
but instead i get something like (varies):
1.3.6.1.2.1.1.1.0 = SmartSTACK ELS100-S24TX2M
1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.52.3.9.1.10.7
1.3.6.1.2.1.1.4.0 = admin
1.3.6.1.2.1.1.5.0 = els
1.3.6.1.2.1.1.3.0 = 26 days, 22:35:02.31
1.3.6.1.2.1.1.6.0 = Computer Room
1.3.6.1.2.1.1.1.0 = SmartSTACK ELS100-S24TX2M
1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.52.3.9.1.10.7
*Currently I have one file per device scanner desired.
i get them from a list of ip , it looks like this. Im also using a little threadpool to keep a limited number of threads at the same time .
for (String s: ips){
output= new FileOutputStream(new File(path+s));
threadpool.add(new DeviceScanner(s, output));
}
I suspect SNMPV1Communicator(device) is not thread-safe. As I can see it's not a part of SNMP4j library.
Taking a wild guess at what's going on here, try putting everything inside a synchronized() block, like this:
synchronized (DeviceScanner.class)
{
for (int j=0; j<num; j++){
read= comm.snmpGetNext(oids);
out.write(read);
this.updateHeaders(read);
}
out.flush();
}
If this works, my guess is right and the reason for the problems you're seeing is that you have many OutputStreamWriters (one on each thread), all writing to a single OutputStream. Each OutputStreamWriter has its own buffer. When this buffer is full, it passes the data to the OutputStream. It's essentially random when each each OutputStreamWriter's buffer is full - it might well be in the middle of a line.
The synchronized block above means that only one thread at a time can be writing to that thread's OutputStreamWriter. The flush() at the end means that before leaving the synchronized block, the OutputStreamWriter's buffer should have been flushed to the underlying OutputStream.
Note that synchronizing in this way on the class object isn't what I'd consider best practice. You should probably be looking at using a single instance of some other kind of stream class - or something like a LinkedBlockingQueue, with all of the SNMP threads passing their data over to a single file-writing thread. I've added the synchronized as above because it was the only thing available to synchronize on within your pasted example code.
You've got multiple threads all using buffered output, and to the same file.
There's no guarantees as to when those threads will be scheduled to run ... the output will be fairly random ordered, dictated by the thread scheduling.
This code has lot of trouble for my AIR 2.0 Native process which I tried to launch Java from AIR application, then the Java.exe terminate itself in the Windows Task manager, I found that new MidiTest() was the caused. Is there a better solution for new instance?
public static void main(String[] arg) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (!(speed.equals(speed_stop))) {
try {
speed = in.readLine();
if(!(Global.newPlayer.equals("1"))){new MidiTest();}
} catch (IOException e) {
System.err.println("Exception while reading the input. " + e);
}
}
}
private MidiPlayer player;
public MidiTest() {
System.out.println("Start player");
// /*
}
There is no alternative to new.
This is the only way to instantiate an object. Even if you use reflection, you're still calling the constructor. You need to track down the problem. Find the exact exception that's being caused, and the exact line number, and then see what you need to do to fix that problem.
I can see that you didn't provide a complete copy of your code. There's an open comment before the close brace, and it's not right. So that means we can't help you any further with the information we have.
No, the only other option for creating a new instance of your class would be using reflection, which is a much more obscure and error prone choice than new. It should not be used unless one really needs to. And even that is loading the class and calling the object's constructor in the end, exactly the same way as new.
I suspect the problem lies somewhere in code you haven't shown to us. Does MidiTest have any (static or nonstatic) initializer blocks? Is that println() statement really the only code in its constructor?
Of course, it helped if you traced down what is the exact error/exception causing the termination and where exactly does it originate from :-)