In linux Socket also is a file, so if exist too many sockets at a time and more than max open files, it will throw below exception:
java.net.SocketException: Too many open files
at sun.nio.ch.Net.socket0(Native Method)
at sun.nio.ch.Net.socket(Net.java:423)
at sun.nio.ch.Net.socket(Net.java:416)
at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:104)
at sun.nio.ch.SelectorProviderImpl.openSocketChannel(SelectorProviderImpl.java:60)
at java.nio.channels.SocketChannel.open(SocketChannel.java:142)
Till now I could understand, but I'm a little confused with below phenomenon.
I executed below command in terminal to find max open file number:
$ ulimit -n
1024
But actually I created about 4091 sockets(SocketChannel) by below code:
while(true) {
new Thread(new Runnable() {
public void run() {
//...
try {
SocketChannel scChannel = SocketChannel.open();
scChannel.connect(new InetSocketAddress(hostname, port));
ByteBuffer buffer = ByteBuffer.allocate(1024);
scChannel.read(buffer);
} catch (IOException e) {
//...
}
}
}).start();
}
and from console I knew until it created 4091 socketChannel, then it threw above exception:
Start client 4091
java.net.SocketException: Too many open files
4091 is more than 1024, so why is so? The result from ulimit is not real number of max open files?
According to n.m.'s advice, I checked if jvm changed ulimit. And I found jvm indeed does something. I executed ulimit command by java code as below:
ProcessBuilder pBuilder = new ProcessBuilder("sh","-c","ulimit -n");
Process p = pBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while(line!=null){
System.out.println(line);
line = reader.readLine();
}
the output is 4096--it is different from terminal output.
But I don't know how and when and where jvm changed the ulimit value.
Related
I want to write UNIT test with SOAP webservices. Webservices work in other jar file, which I try to load Runtime.getRuntime().exec(// java - jar ...). Loading jar file takes 2 min. When loading is in new Thread the test ends before loading jar file will be finished. If loading is in main thread, test is not finished. I try to listen HTTP response with while cycle, but when cycle is working, the jar file is not loading.
#Before
public void setUp() throws Exception {
// Get path of jar file
thread = new Thread() {
public void run() {
try {
Process process = Runtime.getRuntime().exec(path-to-java.exe -jar webservices.jar);
process.waitFor();
process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
int responseCode;
do {
responseCode = getResponseCodeHTTP("http://localhost:8080/services");
} while (responseCode < 200 || responseCode >= 400);
System.out.println("Web services have loaded");
}
public int getResponseCodeHTTP(String urlToRead) throws IOException {
URL url = new URL(urlToRead);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
int result;
try {
conn.connect();
result = conn.getResponseCode();
} catch (ConnectException e){
return 500;
}
return result;
}
OK. I want to write test, which will start the webservices from jar file (loading process takes 1.5 min) and then execute test. To start web services I use Runtime.getRuntime().exec and to understand that them started I use HTTP response code. When the code [200-400) , it means the ws started OK.
I tried to debug code inside new Thread and added code with InputStreamReader and while cycle.
String line;
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
while ((line = reader.readLine()) != null)
System.out.println("[Stdout] " + line);
And test successfully executed. The when I removed the while cycle with readline, the problem had repeated.
I have not understand yet why it worked.
Well, it actually works pretty well on my android studio simulator but when I try to run it on my phone it just crashes.
I just want to send a number to the server and get a response with the data that I need to that number. so this is my code which do that:
thread = new Thread() {
#Override
public void run() {
//server stuff
try {
//Connecting
if(!userClass.equals("")) {
Log.i(debugString, "Attempting to connect to server");
socket = new Socket(hostname, portnumber);
Log.i(debugString, "Connection established!");
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(socket.getOutputStream())));
bw.write("" + userClass);
bw.newLine();
bw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
input = br.readLine();
}
} catch (IOException e) {
Log.e(debugString, e.getMessage());
} finally {
threadComplete = true;
}
}
};
thread.start();
while(!threadComplete)
continue;
then I just use this thread whenever I want to get the updated info for my request like that:
String getUserClass = userClass;
if(!getUserClass.equals(""))
{
threadComplete = false;
userClass = getUserClass;
thread.start();
while (!threadComplete)
continue;
changes.setText(input);
}
else Toast.makeText(this, "Error, choose your class", Toast.LENGTH_SHORT).show();
BTW, in the end of every thread (on the emulator because on my phone it crashes) I get a message:
Skipped 91 frames! The application may be doing too much work on its main thread.
and I have another problem, I also use IntentService to run my app service on the background, and obviously I don't want it to run constantly forever, so I made a loop which contains at the end of each loop a wait() command, but the problem is that when I set the time to wait for longer than 3000 milliseconds or so, the service crashes.
my code for the background service:
synchronized (this) {
int count = 0;
while (count<4) {
try {
wait(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (notifications && !userClass.equals("")) {
new Thread() {
#Override
public void run() {
//server stuff
try {
//Connecting
if (!userClass.equals("")) {
Log.i("debug", "Attempting to connect to server");
socket = new Socket(hostname, portnumber);
Log.i("debug", "Connection established!");
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(socket.getOutputStream())));
bw.write("" + userClass);
bw.newLine();
bw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
input = br.readLine();
}
} catch (IOException e) {
Log.e("debug", e.getMessage());
} finally {
complete = true;
}
}
}.start();
while (!complete)
continue;
Toast.makeText(this, "" + input, Toast.LENGTH_SHORT).show();
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.chanka)
.setContentTitle("ביטול שיעורים: ")
.setContentText(input);
mNotifyMgr.notify(mNotificationId, mBuilder.build());
mNotificationId++;
Toast.makeText(this, "" + input, Toast.LENGTH_SHORT).show();
count++;
}
}
}
This following piece of code is the culprit -
while (!threadComplete)
continue;
You are kind of putting the main thread on a long loop. Android does not allow that. The general construct in these kind of use cases is this -
Step 1 - Show a progress dialog to the user indicating that you are
doing something important and user needs to wait till that is
complete. Show some meaningful text in the progress dialog which makes
sense to the user.
Step 2 - Start a async connection to the server. There are lot of
options in Android to do this. But for your purpose AsyncTask might
be useful. Connect to your server, fetch and parse data in the
doInBackground method of AsyncTask and once the task is complete,
let onPostExecute publish the same to the Main thread.
Step 3 - Once you get back the result from the Async task, you may
dismiss the progress dialog and continue with whatever you were doing.
Please note that the main thread should not be blocked at any time. This is the event handling thread of the app and handles all events (User initiated or system initiated). If the thread is blocked, you get the kind of error you are seeing now. Specifically in your case, Android system is not able to do some draw operations because of the while loop.
Create a new Asynctask and run the socket establisment codes inside it :)
socket = new Socket(hostname, portnumber);
i have a script bash which requires parameters.
when i call it directly from putty, it works, hen i do from my jee program it does not work and does not show me any errors.
This is my java code:
String[] cmdArray = {"sudo", "ssh", "-tt", "root#89.40.112.248", "/root/dve", "-l", "89.40.112.120,89.40.112.248", "you.mp4", "-s",".teeeest.avi" };
List<ObjectNode> listFileNode = new ArrayList<ObjectNode>();
try{
Runtime rt = Runtime.getRuntime();
ProcessBuilder pb = new ProcessBuilder(cmdArray);
Process proc = pb.start(); // Start the process.
System.out.println("Script executing");
rc= proc.waitFor(); // Wait for the process to finish.
System.out.printf("Script executed successfully in ", rc);
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<ERROR___EXEC>");
while ( (line = br.readLine()) != null){
System.out.println(line);
node.put("line",line );
listFileNode.add(node);
}
System.out.println("</ERROR___EXEC>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
InputStream processInputStream =proc.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(processInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
System.out.println("<RESULTAT___EXEC>");
while ( (line = bufferedReader.readLine()) != null){
System.out.println(line);
node.put("lineR",line );
listFileNode.add(node);
}
System.out.println("</RESULTAT___EXEC>");
}catch (Throwable t)
{
t.printStackTrace();
}
please help me i am stuck on this from a week and i don't find solution
You can't use sudo command in the java code. If you need to run root privileged application you need to switch to root before running your java code.
If you want to do it from your java code, you need to call setuid. But I don't know you can call setuid from a java code. For that purpose you may need a C/C++ wrapper for switching to root. Refer:http://unix.stackexchange.com question for writing wrapper.
I'm writing a program that basically acts as an email client as a part of a homework assignment for a class in java. I don't normally resort to the internet to answer my questions, but this is something that goes beyond what the professor is trying to get us to learn/practice, and I need to find a way to fix it.
The Problem: If I run the program, and input the second command (ri), it will prompt me for the number, and then finish by displaying the message, but immediately after, when it goes back into the second iteration of the .run() method the console returns:
Exception in thread "main" java.util.NoSuchElementException: No Line Found
at java.util.scanner.nextLine(Unknown Source)
Here's the code (I'm only including the important stuff...or at least what I think is important).
public class CmdLoop {
private MailClient _client;
Scanner kbd;
private Hashtable<String, ICommand> _commands = new Hashtable<String, ICommand>();
public CmdLoop(MailClient client) {
_client = client;
_commands.put("h", new client.cmd.Help());
_commands.put("ri", new client.cmd.ReadInbox());
kbd = new Scanner(System.in);
}
public void run2() {
System.out.print("\nMail: ");
String command = kbd.nextLine();
ICommand call = _commands.get(command);
if (command.equals("q"))
return;
else if (call == null)
System.out.println(command + " not understood, type h for help");
else if (call.equals(""))
System.out.println(command + " not understood, type h for help");
else call.run(_client);
this.run2();
}
and the ri class:
public class ReadInbox implements ICommand {
#Override
public void run(MailClient client) {
Scanner sc = new Scanner(System.in);
MailBox in = client.getInbox();
if(in.count() < 1)
System.out.println("Inbox empty");
else {
System.out.print("Enter the number of the message you would like to read: ");
int n = Integer.parseInt(sc.nextLine());
if(n > in.count())
System.out.println("Message number " + n + " can't be found");
else
in.getMessage(n - 1).show();
}
sc.close();
}
}
Basically it gets to the end of the ReadInbox.run() call, then it calls this.run2(), returns to the top, outputs "Mail: " and then returns the error. This is what the console looks like in my test:
Mail: ri
Enter the number of the message you would like to read: 1
Date: 2015/04/29 20:24:17
From: Charles Barkley (Charlie) <Charles#gmail.com>
Subj: testerino
this is another test
Mail: Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at client.CmdLoop.run2(CmdLoop.java:28)
at client.CmdLoop.run2(CmdLoop.java:37)
at Main.main(Main.java:29)
If I'm correct, getting it so they both operate off the same scanner would solve my problem, and I feel like I should know how to do that, but I'm drawing a blank. Is there another way as well?
According to the documentation a Scanner will throw that exception "if no line was found". You can prevent that by first calling kbd.hasNextLine() which will tell you if there is something to get. That will wait for a line to be entered as long as the scanner is not closed.
Try this in your run2 method:
String command = null;
if (kbd.hasNextLine())
command = kbd.nextLine();
ICommand call = _commands.get(command);
I found the answer. I got rid of sc.close(); in the ReadInbox class. I have 0 clue why this works, but it does. If anyone has an explanation to offer, much appreciated, otherwise, whatever, at least it works.
I have my uni assignment and it's only very basic coding but I have to do
A user shall be able to store records to a file. On start-up a user shall be able to select a file of records and load these into the program.
I am having trouble with this as it will save but once I close the program and re-open it they are gone, any ones help is appreciated.
This is what I have so far:
private void Save_Click(object sender, EventArgs e)
{
SaveToFile(records, file);
}
private void SaveToFile(List<Client> records, string file)
{
//File.WriteAllText(file, String.Empty);
StreamWriter writer = new StreamWriter(file);
StreamReader reader = new StreamReader(file);
try
{
AddMember();
for (int i = 0; i < records.Count; i++)
{
writer.WriteLine(records[i].WriteToFile());
}
writer.Close();
}
catch (IOException z)
{
MessageBox.Show("Error" + z);
}
}
Before closing the StreamWriter you should call Flush() method. Flush() Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.
reader.clos();
you forgot this
This is just a guess, but it sounds like you might be overwriting the file when you start the program.
In your SaveToFile method, you have the following two lines at the start:
StreamWriter writer = new StreamWriter(file);
StreamReader reader = new StreamReader(file);
The first one will create a new file with the name in file. The second one isn't needed if you're not doing any reading from the file.
Now, if you have a similar block of code in somewhere else in your program that is executed before the SaveToFile method is called, it will overwrite the file (and since you most likely don't write anything in that earlier part of the code, you're left with a blank file).
To prevent this, there are two suggestions I'll offer:
Only create a StreamWriter when you are going to be writing to the file. Any other times you create a StreamWriter, you will be overwriting the existing file.
If you don't want to overwrite the file, you can use the overload of the constructor that takes a second parameter (a boolean) to indicate whether or not to append new data to the file:
StreamWriter writer = new StreamWriter(file, true);
Additionally, I'd suggest getting to know and use using blocks, as this will take care of closing and flushing the StreamWriter (and its underlying stream) for you, even if an exception occurs and is unhandled:
private void SaveToFile(List<Client> records, string file)
{
try
{
AddMember();
// If you don't want to append but overwrite, use:
// using (StreamWriter writer = new StreamWriter(file))
using (StreamWriter writer = new StreamWriter(file, append))
{
for (int i = 0; i < records.Count; i++)
{
writer.WriteLine(records[i].WriteToFile());
}
}
}
catch (IOException z)
{
MessageBox.Show("Error" + z);
}
}