I am creating a Java application that will run on both Linux and Windows. The application will execute native code for multiple-monitor configurations. Because of this, I want to pass the monitor's ID from Java to the native code. This has lead me to Java's ScreenDevice.getIDstring().
Javadocs claim that this method is useful for debugging, but that it also uniquely identifies a monitor. For Linux devices, it returns a usable ID string that allows the native code to quickly retrieve the desired monitor object.
On Windows, however, the method simply returns /display0 for the first display, and then counts upwards for every following display (regardless if a graphics card contains both monitors, or if the monitors are on separate graphics cards).
When it comes to Windows C++ code, I have tried using EnumDisplayDevices and looking at the respective DeviceIDs and DeviceStrings. These do not match the values of Java:
First Monitor - Java = /display0, Windows = \\.\DISPLAY1
Second Monitor - Java = /display1, Windows = \\.\DISPLAY7
I am really confused as to where this /display# ID value is coming from... Where can I acquire the same /display# value when running native Windows C++ code?
Note: It would technically be possible to cycle through all existing displays to try and match the X/Y/width/height between the OS native code and Java, but this would be a lot of work and not very efficient. I would see this as a possible solution, but it is not very ideal.
Related
I am working on a project for personnel allocation during a Navy maintenance availability using AnyLogic. I have the simulation running and have set the parameters (the personnel) variable up and running. However, I am trying to pull the numbers of checks entering the system and those leaving the system for each simulation run to assess the efficiency of the manpower allocation. I'm not able to do that because I cannot convert "agent" to "double". How can I fix this?
I tried creating new agents, trying to make the count into a variable to gather it on the ParametersVariation page and that did not work either.
I know it is possible to get system information in Java and have searched SO for this particular question but have come up empty.
Question:
Can I gather complete system information about all attached monitors? Particularly I am hoping to get a unique ID, model number, or manufacturer of each monitor.
Wayan Saryada for example demonstrated a simple example here that gets basic information about all connected monitors. Code follows to protect from link rot:
//
// Get local graphics environment
//
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] devices = env.getScreenDevices();
int sequence = 1;
for (GraphicsDevice device : devices) {
System.out.println("Screen Number [" + (sequence++) + "]");
System.out.println("Width : " + device.getDisplayMode().getWidth());
System.out.println("Height : " + device.getDisplayMode().getHeight());
System.out.println("Refresh Rate: " + device.getDisplayMode().getRefreshRate());
System.out.println("Bit Depth : " + device.getDisplayMode().getBitDepth());
System.out.println("");
}
This code however produces nothing unique. Its just generic information that is helpful but does not meet my end goal.
Use Case / End Goal:
My intentions is to make a portable application that tracks (detects) what computer/ computer setup you are using and displays the appropriate desktop. One example is on my work computer with a large monitor it lays out my desktop one way and then on my laptop it hides some things; long story short it would show an alternate desktop display (less icons, only the ones I need for work/ home).
I have all that extra stuff worked out but I need a way to track not just what computer I am on but which monitors I have attached at the time. Essentially a "MAC address" for attached monitors; I know that is not a thing. This way on a triple monitor setup for example my application knows what goes where. Then if I remove one monitor it knows what to change to.
So long story short there just is no way to accurately detect in Java which monitor is which in the GraphicsDevice API. There are several other ways to detect this information but again Java runs into the same problem. Java just auto increments the monitors it finds like so:
Display0,
Display1,
Display2
...And so on.
Each time the computer turns on different monitor assignments can happen and each time a monitor turns off the order can change. The same is true if the graphics driver crashes or reboots while in use.
One Solution
This does not solve my original issue: The OP's questions. However I know it is extremely hard to get full human readable system information with Java, especially all attached monitors. I put in a request to dbwiddis on GitHub and he was able to add this feature to Oshi. His Java library pulls everything you need to know about every attached monitor to a computer. A perfect all in one solution for Network Admins.
The Issue Still / Hack
There still is no way (including using other API's accessible through other programming languages) to detect which monitor is which. The "MAC Address" of all your attached monitors if you will. The only way to do this reliably (really a hack) is to pop up a terminal that outputs information that you then can grab with Java. This way Java can manually make the matches. It can go out to Display2 and read the terminal window that is open on it and now we know which monitor is Display2.
I have no code for this right now because it is extremely unreliable and not guaranteed to be cross OS compatible. It should work fine in windows but your will need to execute a batch file or powershell script to get the terminals on the monitors you want.
Just look at the GraphicsDevice API:
https://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsDevice.html#getIDstring%28%29
When running the following code in Matlab, the physical memory usage of Matlab increases until it reaches 90% of my system memory, and crashes the program. This code is part of a larger optimization scheme that will have many more iterations, but it has been simplified here.
import org.parent.modeling.*
for i = 1:100
rTool = Tool('C:/etc');
model = rTool.getModel();
model.initSystem();
rTool.setModel(model);
rTool.run();
end
rTool and model are stored as Java objects in the workspace.
By selectively removing steps from the bottom to top, I've determined that the rTool.run(); step is causing an incremental memory increase during each iteration.
I've tried using a variety of memory clearing techniques with no success
clear classes, clear java, clear rTool model, clear all
I have checked for fragmentation by running the memory command, but it is insignificant.
Below is the actual code that corresponds to the API documentation (https://simtk.org/api_docs/opensim/api_docs/classOpenSim_1_1RRATool.html)
for i = 1:1:4
import org.opensim.modeling.*
rraTool = RRATool('C:\...filename.xml');
model = rraTool.getModel();
model.initSystem();
rraTool.setModel(model);
rraTool.run();
end
Any suggestions for reducing the physical memory increase?
Matlab: 2013
It is difficult to figure out what you are actually doing here, let alone why it is leaking memory. From what I have been able to deduce, you can call Java from MatLab, and you can call C++ directly from Matlab. I cannot figure out if you are calling the C++ library directly, or calling it via a Java (JNI / JNA) wrapper. And if you are doing the latter ... why.
For the Matlab -> C++ case, this page has some tips on avoiding memory leaks: http://www.mathworks.com.au/help/matlab/matlab_external/memory-management-issues.html
For the Matlab -> Java -> C++ case, the leaks could be due to bugs in the Java wrapper or its associated C++-side wrapper code, or a problem in the way that you are using the wrapper. For instance, there could be some dispose method that you need to call. The details should be in the Java API docs ... which you have not been able to locate ... or in the Java source code itself.
I was hoping that there were some general memory clearing Java commands I could use.
There are no such magic commands. You need to figure out where the memory is leaking and fix that.
I'm working on a java project that receives midi events from midi hardware using the javax.sound.midi library. In the documentation, it says that MidiSystem.getMidiDeviceInfo() returns a list of all connected midi hardware. It works for me, but the problem is, it only works once. It takes a moment the first time to actually scan for the devices, but each time after that it will immediately return that same list even if new devices have been connected. Is there a way to force it to rescan? It will rescan if the application is restarted, but I don't want my users to have to restart if they connect a new midi device.
BTW, I'm using Mac OS X... it's been pointed out that behavior may be different for different OS's.
The MidiSystem.getMidiDeviceInfo() gets the full providers list, and extracts the info of the device from each provider.
The MIDIs provider list is recovered from the JDK underlaying class com.sun.media.sound.JDK13Services, through the static method getProviders()
public static synchronized List getProviders(Class serviceClass)
Obtains a List containing installed
instances of the providers for the
requested service. The List of
providers is cached for the period of
time given by cachingPeriod . During
this period, the same List instance is
returned for the same type of
provider. After this period, a new
instance is constructed and returned.
The returned List is immutable.
So, it seems that this class holds thee Providers list in a cache, wich will be reloaded after a certain period. You can set this period to a custom value using the method setCachingPeriod(int seconds). As long as I know, the default caching period is set to 60 seconds.
As an example, to refresh this cache every second, you coud add this line to your code:
com.sun.media.sound.JDK13Services.setCachingPeriod(1);
Please, note that this solution makes use of a Sun propietary class, so it could not be 100% portable.
Lacking any MIDI devices on my work PC, or indeed any kind of Mac, I doubt I'll be able to test it properly, but...
The MidiSystem class seems to use com.sun.media.sound.JDK13Services.getProviders(Class providerClass) to find the list of devices on the system. The API docs for this class state that the list is recreated on a successive call outside of a cachingPeriod, which can be conveniently set by calling setCachingPeriod(int seconds).
With any luck you can just call this once at the start of your application and set it to 5 seconds or something, and it'll magically work. However, the docs also state "This method is only intended for testing.", so I'm not sure quite how effective this approach will be.
Hopefully this is enough to get you started, and I'll keep poking around in the meantime to see if I can find a cleaner way to do this.
I answered this is Update list of Midi Devices in Java as well, but for folks who wind up here, there's now a library that supports this correctly: https://github.com/DerekCook/CoreMidi4J
The library acts a device provider for the MIDI Subsystem, so it's basically a drop-in and all your existing code will work.
I am not the author, but it works well for my needs, and it took a fair bit of searching to find, so I'm posting it here for others who encounter the problem.
I found a solution which uses the JavaFX thread. For some reason this works at least on MacOSX. On a normal thread it doesn't work.
import fx.FX_Platform;
import javafx.embed.swing.JFXPanel;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
public class miditest {
static public void main( String[] args ) {
// **** Just to init FX platform
new JFXPanel();
new Thread( () -> {
for( int ix=0; ix<1000; ix++ ) {
try {
Thread.sleep(2000);
} catch( InterruptedException e ) {
}
FX_Platform.runLater( () -> {
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
System.out.println("FOUND: " + infos.length);
for( MidiDevice.Info midiinfo : infos ) {
System.out.println(midiinfo);
}
});
}
}).start();
}
}
This sounds like is could be an OS specifx bug but I can think of a get around.
In java you can run external commands to the OS. (A quick google, gave me this example http://www.javafaq.nu/java-example-code-186.html it looks OK and gives you the idea).
On checking for new devices you could send an external command to run a simple java program that quickly queries the midi devices using MidiSystem.getMidiDeviceInfo() and outputs the results to a text file or you could grab the output from the BufferedReader object.
Also remember that the external program used to query midi devices doesn't have to be written in Java incase Java causes you more problems. Alternatively you could just query the OS for connected devices and use grep to filter the results.
Hope this helps.
After recording just the appearance of the logon window of our Java app in LR/VUgen 9.51 using the RMI protocol, the resulting script replays with a java.lang.ArrayIndexOutOfBoundsException. The code fragment looks like this:
_hashtable2 = new Hashtable();
_object_array3 = ((java.util.Collection)_hashtable2.values()).toArray();
_hashtable2.put("sessionId",(java.lang.String)_object_array3[0]); //yields exception!
_boolean1 = _mopsconstantserverif1.psi_requiresHostCommunication((java.util.Hashtable)_hashtable2, (java.util.Vector)null);
Of course generating an empty hashtable, converting it to an array, and referencing its first array element must yield an ArrayIndexOutOfBoundsException, right? But why does LR generate this kind of code at all? Is this a bug, or what am I doing wrong? I have never seen problems like this one when using RMI and LoadRunner.
Since the cause of the playback error is quite obvious and independent of the remainder of the recorded code (i.e. limited to the four statements shown), I try to ask without showing the whole script...
Ahh, RMI, the bane of my existence. I so dislike the RMI/Java combination in LoadRunner I do as much RMI work in Winsock as I can. You might consider the use of Winsock as a plan B option to avoid the Java issues you are experiencing today as Winsock is a straight C virtual user type. The use of a Windows sockets virtual user avoids the complications of the dark magic of Java and LoadRunner, plus it's lighter weight on the resource front and it's faster as a result. And, I am just a glutton for punishment on the Winsock front plus it keeps the C skills razor sharp!