I want to be able to execute the .Jar file, and if the heap space isn't set big enough, it should launch a new JVM with the same .Jar file, but set with a bigger heap space, and then close the first JVM and .Jar.
I've tried using the ProcessBuilder, but I can't get it to work.
It has to work cross platform.
-ONi
I have found the solution, and it works cross platform. To restart the JVM from code, use the following. This answer is taken from another question I found after hours of search in here. If you want, you can follow it with an System.exit(0), to terminate the JVM that started the new process, after a call to this method.
public static void startSecondJVM() throws Exception {
String separator = System.getProperty("file.separator");
String classpath = System.getProperty("java.class.path");
String path = System.getProperty("java.home")
+ separator + "bin" + separator + "java";
ProcessBuilder processBuilder =
new ProcessBuilder(path, "-Xmx1024m", "-cp",
classpath,
Main.class.getName());
Process process = processBuilder.start();
}
You can launch java with an initial heap size, and also specify a maximum heap size which will be only be used as required. I'm not sure what you're trying to do but it might emulate the behaviour you want?
java -Xms256m -Xmx1g -jar myapp.jar
In this example you start with 256M, if the app needs more memory it will take it, incrementally, up until 1G.
You might try combining these two sources.
MemoryRecoveryTest.java
Makes attempts to recover from an OutOfMemoryError.
/*License - LGPL
<h3>Recovery from an OutOfMemory Error</h3>
<p>The JavaDocs for Error state, in the first sentence..
<blockquote>"An Error is a subclass of Throwable that indicates
serious problems that a reasonable application should
not try to catch."</blockquote>
<p>This advice has led to the fallacy that an OutOfMemoryError
should not be caught and dealt with.But this demo. shows
that it is quite easy to recover to the point of providing
the user with meaningful information, and advice on how to
proceed.
<p>I aim to make my applications 'unreasonable'.;-)
*/
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JOptionPane;
import javax.swing.JDialog;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
/** A demo. showing recovery from an OutOfMemoryError.
Our options once an OOME is encountered are relatively
few, but we can still warn the end user and provide
advice on how to correct the problem.
#author Andrew Thompson */
public class MemoryRecoveryTest {
public static void main(String[] args) {
// reserve a buffer of memory
byte[] buffer = new byte[2^10];
ArrayList<Object> list = new ArrayList<Object>();
final JProgressBar memory = new JProgressBar(
0,
(int)Runtime.getRuntime().totalMemory());
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
memory.setValue(
(int)Runtime.getRuntime().freeMemory() );
}
};
Timer timer = new Timer(500, listener);
timer.start();
JDialog dialog = new JDialog();
dialog.setTitle("Available Memory");
JPanel memoryPanel = new JPanel();
memoryPanel.add(memory);
memoryPanel.setBorder(new EmptyBorder(25,25,25,25));
dialog.add( memoryPanel );
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
dialog.addWindowListener( new WindowAdapter(){
#Override
public void windowClosing(WindowEvent we) {
System.exit(0);
}
} );
// prepare a memory warning panel in advance
JPanel memoryWarning = new JPanel();
memoryWarning.add( new JLabel(
"<HTML><BODY>There is not enough memory to" +
" complete the task!<BR> Use a variant " +
" of the application that assigns more memory.") );
try {
// do our 'memory intensive' task
while(true) {
list.add( new Object() );
}
} catch(OutOfMemoryError oome) {
// provide the VM with some memory 'breathing space'
// by clearing the buffer
buffer = null;
// tell the user what went wrong, and how to fix it
JOptionPane.showMessageDialog(
dialog,
memoryWarning,
"Out of Memory!",
JOptionPane.ERROR_MESSAGE);
}
}
}
IWantToBeBig.java
Ensures a Process is started with a memory size specified.
import java.awt.EventQueue;
import javax.swing.JOptionPane;
import java.io.File;
class IWantToBeBig {
public static void main(String[] args) throws Exception {
if (args.length==0) {
ProcessBuilder pb = new ProcessBuilder(
"java",
"-jar",
"-Xmx512m",
"big.jar",
"anArgument"
);
pb.directory(new File("."));
Process process = pb.start();
process.waitFor();
System.out.println("Exit value: " + process.exitValue());
} else {
Runnable r = new Runnable() {
public void run() {
JOptionPane.showMessageDialog(
null,
"Max Memory: " +
Runtime.getRuntime().maxMemory() +
" bytes.");
}
};
EventQueue.invokeLater(r);
}
}
}
I'd do this kind of work in an outer script file - in pseudo code:
$heap := 128
$ok := true
do {
exitCode = java -Xmx$heapM -jar myApp.jar
if (exitCode = OOME) {
heap += 128
$ok := false
}
while(!$ok)
Catch OOME and exiting with a custom code should always be possible. There's one problem with this approach - if the $heap value exceeds the maximum heap space that is possible for the target system (example: ~1.4GByte on Win32 systems) then it will not terminate.
Note: this is just an answer to the question - usually one would assign a high amount of memory and/or fight the memory leaks - but I don't know the actual requirments/restrictions
Related
I am running a tool that runs an external Java program several times in its operation. The external tool starts with opening a JOptionPane inside a JFrame.
Here is a test script I wrote to try to solve my issue.
import java.io.File;
public class Test {
public static void main(String[] args) throws Exception {
for(int i=0; i<6; i++) {
//Thread.sleep(1000);
String toRun = "java -jar \"" + "C:\\Folder\\File.jar" + "\" " + i;
Runtime.getRuntime().exec(toRun, null, new File("C:\\Folder"));
}
}
}
When this runs, only the final run's JOptionPane (i=5) appears, but it seems that others are "trying" to appear as panes seem to be opening and immediately closing.
When I uncomment the Thread.sleep however, all of the panes open separately. If i set the sleep to 300 (0.3 seconds) about half of the panes appear, usually the first and last ones.
I would like to find a way to run all instances of the external program fully without needing to use Thread.sleep() at all, if possible.
Edit: As per requirement's I've minimalised my external program as well.
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class File {
static JFrame frame = new JFrame("Frame");
private static String doc1Address = "C:\\Folder\\doc1.csv";
private static String doc2Address = "C:\\Folder\\doc2.csv";
public static void main(String[] args) throws Exception {
if(args.length == 1) {
SimpleDateFormat form = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss");
Date date = new Date();
String currentDate = form.format(date);
//Save Backup of doc1
String doc1BackAddress = doc1Log.substring(0, doc1Log.length()-15) + "doc1Back " + currentDate + ".csv";
Path todoc1 = Paths.get(doc1Address);
Path todoc1Back = Paths.get(doc1BackAddress);
Files.copy(todoc1, todoc1Back);
Files.setAttribute(todoc1Back, "dos:readonly", true);
//Save Backup of doc2
String doc2BackAddress = doc2Log.substring(0, doc2Log.length()-16) + "doc2Back " + currentDate + ".csv";
Path todoc2 = Paths.get(doc2Address);
Path todoc2Back = Paths.get(doc2BackAddress);
Files.copy(todoc2, todoc2Back);
Files.setAttribute(todoc2Back, "dos:readonly", true);
//Format JFrame
frame.pack();
frame.setLodoc1ionRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JOptionPane.showMessageDialog(frame, args[0]);
frame.dispose();
}
}
}
Found my own issue; since the backup files use the format yyyy-MM-dd hh-mm-ss, and files saved during the same second result in a FileAlreadyExists Exception, meaning only the first file to finish saving allows the program to continue running.
Having a 1 second pause results in the files having different save names, so no error occurs.
Having a sub-1 second pause results in some file name overlap, but some different names too, hence some files appear.
Solution: either change the name format (i.e. include milliseconds), or include the backup functions in an if-statement, that is ignored if the file with the same time already exists.
(also; thank you #ErwinBolwidt, in being encouraged to format my question properly I realised that the issue in my code was not where I assumed it to be).
I need to get the free available disk space for all disks in system, or all partitions, I don't mind that. (I dont have to use Sigar, but I am using it already on the project for some other processes, so I can use it for this as well)
I am using Sigar API and got this
public double getFreeHdd() throws SigarException{
FileSystemUsage f= sigar.getFileSystemUsage("/");
return ( f.getAvail());
}
But this only gives me the system partition (root), how can i get a list of all partition and loop them to get their free space?
I tried this
FileSystemView fsv = FileSystemView.getFileSystemView();
File[] roots = fsv.getRoots();
for (int i = 0; i < roots.length; i++) {
System.out.println("Root: " + roots[i]);
}
But it only returns the root dir
Root: /
Thanks
Edit
it seems that I could use
FileSystem[] fslist = sigar.getFileSystemList();
But the results i am getting do not match the ones i get from the terminal. On the other hand on this system I am working on, i have 3 disks with a total 12 partitions, so i might be loosing something there. Will try it on some other system in case i can make something useful out of the results.
We use SIGAR extensively for cross-platform monitoring. This is the code we use to get the file system list:
/**
* #return a list of directory path names of file systems that are local or network - not removable media
*/
public static Set<String> getLocalOrNetworkFileSystemDirectoryNames() {
Set<String> ret = new HashSet<String>();
try {
FileSystem[] fileSystemList = getSigarProxy().getFileSystemList();
for (FileSystem fs : fileSystemList) {
if ((fs.getType() == FileSystem.TYPE_LOCAL_DISK) || (fs.getType() == FileSystem.TYPE_NETWORK)) {
ret.add(fs.getDirName());
}
}
}
catch (SigarException e) {
// log or rethrow as appropriate
}
return ret;
}
You can then use that as the input to other SIGAR methods:
FileSystemUsage usageStats = getSigarProxy().getFileSystemUsage(fileSystemDirectoryPath);
The getSigarProxy() is just a convenience base method:
// The Humidor handles thread safety for a single instance of a Sigar object
static final private SigarProxy sigarProxy = Humidor.getInstance().getSigar();
static final protected SigarProxy getSigarProxy() {
return sigarProxy;
}
You can use java.nio.file.FileSystems to get a list of java.nio.file.FileStorages and then see the usable/available space. Per instance (assuming that you are using Java 7+):
import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.util.function.Consumer;
public static void main(String[] args) {
FileSystem fs = FileSystems.getDefault();
fs.getFileStores().forEach(new Consumer<FileStore>() {
#Override
public void accept(FileStore store) {
try {
System.out.println(store.getTotalSpace());
System.out.println(store.getUsableSpace());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
Also, keep in mind that FileStore.getUsableSpace() returns the size in bytes. See the docs for more information.
As the title says, I'm wondering if it is possible for a program written in Java (and only java) to relaunch himself (preferably a .jar) with administrator privileges, showing in the way the native Windows UAC (in order to make it more trustable for the user), i did my homework and found out that it is possible to accomplish this using bridges between c++ and java, but i would really like to do this as a pure java project.
P.S: In the remote case that this result to be impossible, can someone show me the "easy" way to do this using another language (i mean, I've found tutorials, but they are to complicated for something I think it should not be that complicated).
P.S2: In case it is possible to accomplish this, would it work, on other platforms (OS X, Linux)
It cannot be done in pure java.
Best bet would be to write this to a file:
#echo Set objShell = CreateObject("Shell.Application") > %temp%\sudo.tmp.vbs
#echo args = Right("%*", (Len("%*") - Len("%1"))) >> %temp%\sudo.tmp.vbs
#echo objShell.ShellExecute "%1", args, "", "runas" >> %temp%\sudo.tmp.vbs
#cscript %temp%\sudo.tmp.vbs
and save it as something.bat in Windows temp directory (as we have access to this).
You would then execute this from your application using Runtime or ProcessBuilder and exit your application (System.exit(0);).
You should add an immediate start up check to your application that checks if the program has elevation, if it has proceed if not re-run the batch and exit.
Here is an example I made (this must be run when compiled as a Jar or it wont work):
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;
/**
*
* #author David
*/
public class UacTest {
public static String jarName = "UacTest.jar", batName = "elevate.bat";
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
if (checkForUac()) {//uac is on
JOptionPane.showMessageDialog(null, "I am not elevated");
//attempt elevation
new UacTest().elevate();
System.exit(0);
} else {//uac is not on
//if we get here we are elevated
JOptionPane.showMessageDialog(null, "I am elevated");
}
}
private static boolean checkForUac() {
File dummyFile = new File("c:/aaa.txt");
dummyFile.deleteOnExit();
try {
//attempt to craete file in c:/
try (FileWriter fw = new FileWriter(dummyFile, true)) {
}
} catch (IOException ex) {//we cannot UAC muts be on
//ex.printStackTrace();
return true;
}
return false;
}
private void elevate() {
//create batch file in temporary directory as we have access to it regardless of UAC on or off
File file = new File(System.getProperty("java.io.tmpdir") + "/" + batName);
file.deleteOnExit();
createBatchFile(file);
runBatchFile();
}
private String getJarLocation() {
return getClass().getProtectionDomain().getCodeSource().getLocation().getPath().substring(1);
}
private void runBatchFile() {
//JOptionPane.showMessageDialog(null, getJarLocation());
Runtime runtime = Runtime.getRuntime();
String[] cmd = new String[]{"cmd.exe", "/C",
System.getProperty("java.io.tmpdir") + "/" + batName + " java -jar " + getJarLocation()};
try {
Process proc = runtime.exec(cmd);
//proc.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void createBatchFile(File file) {
try {
try (FileWriter fw = new FileWriter(file, true)) {
fw.write(
"#echo Set objShell = CreateObject(\"Shell.Application\") > %temp%\\sudo.tmp.vbs\r\n"
+ "#echo args = Right(\"%*\", (Len(\"%*\") - Len(\"%1\"))) >> %temp%\\sudo.tmp.vbs\r\n"
+ "#echo objShell.ShellExecute \"%1\", args, \"\", \"runas\" >> %temp%\\sudo.tmp.vbs\r\n"
+ "#cscript %temp%\\sudo.tmp.vbs\r\n"
+ "del /f %temp%\\sudo.tmp.vbs\r\n");
}
} catch (IOException ex) {
//ex.printStackTrace();
}
}
}
Use a batch file and the runas command.
I doubt "only Java". At best you would have to have a JNI wrapper around the MSFT module. Unless just invoking the exe using ProcessBuilder counts as "only Java" -- your code to bring up the user console would be only Java but not what it invokes. IOW, Win does not come with a Java API
To relaunch your application elevated, you have to call ShellExecute or ShellExecuteEx function from Windows API and use runas verb.
You can use these API in pure Java with JNA library.
To relaunch yourself, you would have to know the full path to java.exe or javaw.exe, the command-line parameters (class path, if any, and the path to your jar). Obviously you can get this information by using Windows API.
What do you mean by remote case?
You cannot start remote elevated process this way.
You can re-launch your application elevated from a network share. Yet it won't work with mapped drives: after elevation there's no access to user's mapped drives.
No, this can't work on other platforms. UAC is a Windows feature. It's similar to sudo in Linux in some ways, so for Linux you can use sudo $pathtojava/java.exe <yourparameters>. However this won't work nicely if your application is not started from a console. Window Managers usually have wrappers which prompt for password in a GUI dialog.
Just do this with Hackaprofaw (v29). Also it was released in 2002 and started development in 1997 soooooo ye. in 2021 its on version 29.10.7 but-
if raw ram = 0
disable "featureII" program = "JAVA(math = any)"
run on "Hackaprofaw (math = v29(x))
when "featureII" disabled
end
This is my source code of Main.java. It was grabbed from neo4j-apoc-1.0 examples. The goal of modification to store 1M records of 2 nodes and 1 relation:
package javaapplication2;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.EmbeddedGraphDatabase;
public class Main
{
private static final String DB_PATH = "neo4j-store-1M";
private static final String NAME_KEY = "name";
private static enum ExampleRelationshipTypes implements RelationshipType
{
EXAMPLE
}
public static void main(String[] args)
{
GraphDatabaseService graphDb = null;
try
{
System.out.println( "Init database..." );
graphDb = new EmbeddedGraphDatabase( DB_PATH );
registerShutdownHook( graphDb );
System.out.println( "Start of creating database..." );
int valIndex = 0;
for(int i=0; i<1000; ++i)
{
for(int j=0; j<1000; ++j)
{
Transaction tx = graphDb.beginTx();
try
{
Node firstNode = graphDb.createNode();
firstNode.setProperty( NAME_KEY, "Hello" + valIndex );
Node secondNode = graphDb.createNode();
secondNode.setProperty( NAME_KEY, "World" + valIndex );
firstNode.createRelationshipTo(
secondNode, ExampleRelationshipTypes.EXAMPLE );
tx.success();
++valIndex;
}
finally
{
tx.finish();
}
}
}
System.out.println("Ok, client processing finished!");
}
finally
{
System.out.println( "Shutting down database ..." );
graphDb.shutdown();
}
}
private static void registerShutdownHook( final GraphDatabaseService graphDb )
{
// Registers a shutdown hook for the Neo4j instance so that it
// shuts down nicely when the VM exits (even if you "Ctrl-C" the
// running example before it's completed)
Runtime.getRuntime().addShutdownHook( new Thread()
{
#Override
public void run()
{
graphDb.shutdown();
}
} );
}
}
After a few iterations (around 150K) I got error message:
"java.lang.OutOfMemoryError: Java heap space
at java.nio.HeapByteBuffer.(HeapByteBuffer.java:39)
at java.nio.ByteBuffer.allocate(ByteBuffer.java:312)
at org.neo4j.kernel.impl.nioneo.store.PlainPersistenceWindow.(PlainPersistenceWindow.java:30)
at org.neo4j.kernel.impl.nioneo.store.PersistenceWindowPool.allocateNewWindow(PersistenceWindowPool.java:534)
at org.neo4j.kernel.impl.nioneo.store.PersistenceWindowPool.refreshBricks(PersistenceWindowPool.java:430)
at org.neo4j.kernel.impl.nioneo.store.PersistenceWindowPool.acquire(PersistenceWindowPool.java:122)
at org.neo4j.kernel.impl.nioneo.store.CommonAbstractStore.acquireWindow(CommonAbstractStore.java:459)
at org.neo4j.kernel.impl.nioneo.store.AbstractDynamicStore.updateRecord(AbstractDynamicStore.java:240)
at org.neo4j.kernel.impl.nioneo.store.PropertyStore.updateRecord(PropertyStore.java:209)
at org.neo4j.kernel.impl.nioneo.xa.Command$PropertyCommand.execute(Command.java:513)
at org.neo4j.kernel.impl.nioneo.xa.NeoTransaction.doCommit(NeoTransaction.java:443)
at org.neo4j.kernel.impl.transaction.xaframework.XaTransaction.commit(XaTransaction.java:316)
at org.neo4j.kernel.impl.transaction.xaframework.XaResourceManager.commit(XaResourceManager.java:399)
at org.neo4j.kernel.impl.transaction.xaframework.XaResourceHelpImpl.commit(XaResourceHelpImpl.java:64)
at org.neo4j.kernel.impl.transaction.TransactionImpl.doCommit(TransactionImpl.java:514)
at org.neo4j.kernel.impl.transaction.TxManager.commit(TxManager.java:571)
at org.neo4j.kernel.impl.transaction.TxManager.commit(TxManager.java:543)
at org.neo4j.kernel.impl.transaction.TransactionImpl.commit(TransactionImpl.java:102)
at org.neo4j.kernel.EmbeddedGraphDbImpl$TransactionImpl.finish(EmbeddedGraphDbImpl.java:329)
at javaapplication2.Main.main(Main.java:62)
28.05.2010 9:52:14 org.neo4j.kernel.impl.nioneo.store.PersistenceWindowPool logWarn
WARNING: [neo4j-store-1M\neostore.propertystore.db.strings] Unable to allocate direct buffer"
Guys! Help me plzzz, what I did wrong, how can I repair it? Tested on platform Windows XP 32bit SP3. Maybe solution within creation custom configuration?
thnx 4 every advice!
this is a configuration issue on Windows, where Neo4j cannot use memory mapped buffers. Instead, a Java Buffer on the heap is created. In 1.0 this buffer was 470MB per default, which is more than the default heap for the Windows JVM. You have two options:
Switch to APOC 1.1-SNAPSHOT instead of 1.0 in your pom.xml which has an autoconfiguration, assigning max 50% of the available JVM heap to Neo4j
Adjust the JVM heap to more (e.g. 512Mb) by running Java with
java -Xmx512m ....
You can even insert that under JVM arguments in the Run Configurations in Eclipse
Let us know if this helps!
Also, doing a full transaction for every node pair is going to take a long time. Try opening a transaction in the first loop and do commits only every 1000 node pairs?
/peter
I have a piece of server-ish software written in Java to run on Windows and OS X. (It is not running on a server, but just a normal user's PC - something like a torrent client.) I would like the software to signal to the OS to keep the machine awake (prevent it from going into sleep mode) while it is active.
Of course I don't expect there to be a cross platform solution, but I would love to have some very minimal C programs/scripts that my app can spawn to inform the OS to stay awake.
Any ideas?
I use this code to keep my workstation from locking. It's currently only set to move the mouse once every minute, you could easily adjust it though.
It's a hack, not an elegant solution.
import java.awt.*;
import java.util.*;
public class Hal{
public static void main(String[] args) throws Exception{
Robot hal = new Robot();
Random random = new Random();
while(true){
hal.delay(1000 * 60);
int x = random.nextInt() % 640;
int y = random.nextInt() % 480;
hal.mouseMove(x,y);
}
}
}
On Windows, use the SystemParametersInfo function. It's a Swiss army-style function that lets you get/set all sorts of system settings.
To disable the screen shutting off, for instance:
SystemParametersInfo( SPI_SETPOWEROFFACTIVE, 0, NULL, 0 );
Just be sure to set it back when you're done...
A much cleaner solution is use JNA to tap into the native OS API. Check your platform at runtime, and if it happens to be Windows then the following will work:
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
import com.sun.jna.platform.win32.WTypes.LPWSTR;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.win32.StdCallLibrary;
/**
* Power management.
*
* #see https://stackoverflow.com/a/20996135/14731
*/
public enum PowerManagement
{
INSTANCE;
#FieldOrder({"version", "flags", "simpleReasonString"})
public static class REASON_CONTEXT extends Structure
{
public static class ByReference extends REASON_CONTEXT implements Structure.ByReference
{
}
public ULONG version;
public DWORD flags;
public LPWSTR simpleReasonString;
}
private interface Kernel32 extends StdCallLibrary
{
HANDLE PowerCreateRequest(REASON_CONTEXT.ByReference context);
/**
* #param powerRequestHandle the handle returned by {#link #PowerCreateRequest(REASON_CONTEXT.ByReference)}
* #param requestType requestType is the ordinal value of {#link PowerRequestType}
* #return true on success
*/
boolean PowerSetRequest(HANDLE powerRequestHandle, int requestType);
/**
* #param powerRequestHandle the handle returned by {#link #PowerCreateRequest(REASON_CONTEXT.ByReference)}
* #param requestType requestType is the ordinal value of {#link PowerRequestType}
* #return true on success
*/
boolean PowerClearRequest(HANDLE powerRequestHandle, int requestType);
enum PowerRequestType
{
PowerRequestDisplayRequired,
PowerRequestSystemRequired,
PowerRequestAwayModeRequired,
PowerRequestMaximum
}
}
private final Kernel32 kernel32;
private HANDLE handle = null;
PowerManagement()
{
// Found in winnt.h
ULONG POWER_REQUEST_CONTEXT_VERSION = new ULONG(0);
DWORD POWER_REQUEST_CONTEXT_SIMPLE_STRING = new DWORD(0x1);
kernel32 = Native.load("kernel32", Kernel32.class);
REASON_CONTEXT.ByReference context = new REASON_CONTEXT.ByReference();
context.version = POWER_REQUEST_CONTEXT_VERSION;
context.flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
context.simpleReasonString = new LPWSTR("Your reason for changing the power setting");
handle = kernel32.PowerCreateRequest(context);
if (handle == WinBase.INVALID_HANDLE_VALUE)
throw new AssertionError(Native.getLastError());
}
/**
* Prevent the computer from going to sleep while the application is running.
*/
public void preventSleep()
{
if (!kernel32.PowerSetRequest(handle, Kernel32.PowerRequestType.PowerRequestSystemRequired.ordinal()))
throw new AssertionError("PowerSetRequest() failed");
}
/**
* Allow the computer to go to sleep.
*/
public void allowSleep()
{
if (!kernel32.PowerClearRequest(handle, Kernel32.PowerRequestType.PowerRequestSystemRequired.ordinal()))
throw new AssertionError("PowerClearRequest() failed");
}
}
Then when the user runs powercfg /requests they see:
SYSTEM:
[PROCESS] \Device\HarddiskVolume1\Users\Gili\.jdks\openjdk-15.0.2\bin\java.exe
Your reason for changing the power setting
You should be able to do something similar for macOS and Linux.
Adding to scarcher2's code snippet above and moving mouse by only 1 pixel. I have moved the mouse twice so that some change occurs even if pointer is on extremes:
while(true){
hal.delay(1000 * 30);
Point pObj = MouseInfo.getPointerInfo().getLocation();
System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y);
hal.mouseMove(pObj.x + 1, pObj.y + 1);
hal.mouseMove(pObj.x - 1, pObj.y - 1);
pObj = MouseInfo.getPointerInfo().getLocation();
System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y);
}
I have a very brute-force technique of moving the mouse 1 point in the x direction and then back every 3 minutes.
There may me a more elegant solution but it's a quick fix.
Wouldn't all the suggestions moving the mouse back and forth drive the user crazy? I know I'd remove any app that would do that as soon as I can isolate it.
Here is completed Batch file that generates java code, compile it, cleans the generated files, and runs in the background.. (jdk is required on your laptop)
Just save and run this as a Bat File. (somefilename.bat) ;)
#echo off
setlocal
rem rem if JAVA is set and run from :startapp labeled section below, else the program exit through :end labeled section.
if not "[%JAVA_HOME%]"=="[]" goto start_app
echo. JAVA_HOME not set. Application will not run!
goto end
:start_app
echo. Using java in %JAVA_HOME%
rem writes below code to Energy.java file.
#echo import java.awt.MouseInfo; > Energy.java
#echo import java.awt.Point; >> Energy.java
#echo import java.awt.Robot; >> Energy.java
#echo //Mouse Movement Simulation >> Energy.java
#echo public class Energy { >> Energy.java
#echo public static void main(String[] args) throws Exception { >> Energy.java
#echo Robot energy = new Robot(); >> Energy.java
#echo while (true) { >> Energy.java
#echo energy.delay(1000 * 60); >> Energy.java
#echo Point pObj = MouseInfo.getPointerInfo().getLocation(); >> Energy.java
#echo Point pObj2 = pObj; >> Energy.java
#echo System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y); >> Energy.java
#echo energy.mouseMove(pObj.x + 10, pObj.y + 10); >> Energy.java
#echo energy.mouseMove(pObj.x - 10, pObj.y - 10); >> Energy.java
#echo energy.mouseMove(pObj2.x, pObj.y); >> Energy.java
#echo pObj = MouseInfo.getPointerInfo().getLocation(); >> Energy.java
#echo System.out.println(pObj.toString() + "x>>" + pObj.x + " y>>" + pObj.y); >> Energy.java
#echo } >> Energy.java
#echo } >> Energy.java
#echo } >> Energy.java
rem compile java code.
javac Energy.java
rem run java application in background.
start javaw Energy
echo. Your Secret Energy program is running...
goto end
:end
rem clean if files are created.
pause
del "Energy.class"
del "Energy.java"
I've been using pmset to control sleep mode on my Mac for awhile now, and it's pretty easy to integrate. Here's a rough example of how you could call that program from Java to disable/enable sleep mode. Note that you need root privileges to run pmset, and therefore you'll need them to run this program.
import java.io.BufferedInputStream;
import java.io.IOException;
/**
* Disable sleep mode (record current setting beforehand), and re-enable sleep
* mode. Works with Mac OS X using the "pmset" command.
*/
public class SleepSwitch {
private int sleepTime = -1;
public void disableSleep() throws IOException {
if (sleepTime != -1) {
// sleep time is already recorded, assume sleep is disabled
return;
}
// query pmset for the current setting
Process proc = Runtime.getRuntime().exec("pmset -g");
BufferedInputStream is = new BufferedInputStream(proc.getInputStream());
StringBuffer output = new StringBuffer();
int c;
while ((c = is.read()) != -1) {
output.append((char) c);
}
is.close();
// parse the current setting and store the sleep time
String outString = output.toString();
String setting = outString.substring(outString.indexOf(" sleep\t")).trim();
setting = setting.substring(7, setting.indexOf(" ")).trim();
sleepTime = Integer.parseInt(setting);
// set the sleep time to zero (disable sleep)
Runtime.getRuntime().exec("pmset sleep 0");
}
public void enableSleep() throws IOException {
if (sleepTime == -1) {
// sleep time is not recorded, assume sleep is enabled
return;
}
// set the sleep time to the previously stored value
Runtime.getRuntime().exec("pmset sleep " + sleepTime);
// reset the stored sleep time
sleepTime = -1;
}
}
You can use the program Caffeine caffiene to keep your workstation awake. You could run the program via the open command in os X.
On OS X, just spawn caffeinate. This will prevent the system from sleeping until caffeinate is terminated.
In Visual Studio create a simple form.
From the toolbar, drag a Timer control onto the form.
In the Init code, set the timer interval to 60 seconds (60000 ms.).
Implement the timer callback with the following code "SendKeys.Send("{F15}");"
Run the new program.
No mouse movement needed.
Edit: At least on my Army workstation, simply programmatically generating mouse and key messages isn't enough to keep my workstation logged in and awake. The early posters with the Java Robot class are on the right track. JAVA Robot works on or below the OS's HAL (Hardware Abstraction Layer) However I recreated and tested the Java/Robot solution and it did not work - until I added a Robot.keyPress(123) to the code.
To go with the solution provided by user Gili for Windows using JNA, here's the JNA solution for MacOS.
First, the JNA library interface:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.platform.mac.CoreFoundation;
import com.sun.jna.ptr.IntByReference;
public interface ExampleIOKit extends Library {
ExampleIOKit INSTANCE = Native.load("IOKit", ExampleIOKit.class);
CoreFoundation.CFStringRef kIOPMAssertPreventUserIdleSystemSleep = CoreFoundation.CFStringRef.createCFString("PreventUserIdleSystemSleep");
CoreFoundation.CFStringRef kIOPMAssertPreventUserIdleDisplaySleep = CoreFoundation.CFStringRef.createCFString("PreventUserIdleDisplaySleep");
int kIOReturnSuccess = 0;
int kIOPMAssertionLevelOff = 0;
int kIOPMAssertionLevelOn = 255;
int IOPMAssertionCreateWithName(CoreFoundation.CFStringRef assertionType,
int assertionLevel,
CoreFoundation.CFStringRef reasonForActivity,
IntByReference assertionId);
int IOPMAssertionRelease(int assertionId);
}
Here's an example of invoking the JNA method to turn sleep prevention on or off:
public class Example {
private static final Logger _log = LoggerFactory.getLogger(Example.class);
private int sleepPreventionAssertionId = 0;
public void updateSleepPrevention(final boolean isEnabled) {
if (isEnabled) {
if (sleepPreventionAssertionId == 0) {
final var assertionIdRef = new IntByReference(0);
final var reason = CoreFoundation.CFStringRef.createCFString(
"Example preventing display sleep");
final int result = ExampleIOKit.INSTANCE.IOPMAssertionCreateWithName(
ExampleIOKit.kIOPMAssertPreventUserIdleDisplaySleep,
ExampleIOKit.kIOPMAssertionLevelOn, reason, assertionIdRef);
if (result == ExampleIOKit.kIOReturnSuccess) {
_log.info("Display sleep prevention enabled");
sleepPreventionAssertionId = assertionIdRef.getValue();
}
else {
_log.error("IOPMAssertionCreateWithName returned {}", result);
}
}
}
else {
if (sleepPreventionAssertionId != 0) {
final int result = ExampleIOKit.INSTANCE.IOPMAssertionRelease(sleepPreventionAssertionId);
if (result == ExampleIOKit.kIOReturnSuccess) {
_log.info("Display sleep prevention disabled");
}
else {
_log.error("IOPMAssertionRelease returned {}", result);
}
sleepPreventionAssertionId = 0;
}
}
}
}
Wouldn't it be easier to disable the power management on the server? It might be argued that servers shouldn't go into powersave mode?
This code moves the pointer to the same location where it already is so the user doesn't notice any difference.
while (true) {
Thread.sleep(180000);//this is how long before it moves
Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
Robot rob = new Robot();
rob.mouseMove(mouseLoc.x, mouseLoc.y);
}
Run a command inside a timer like pinging the server..
I'd just do a function (or download a freebie app) that moves the mouse around. Inelegant, but easy.
This will work:
public class Utils {
public static void main(String[] args) throws AWTException {
Robot rob = new Robot();
PointerInfo ptr = null;
while (true) {
rob.delay(4000); // Mouse moves every 4 seconds
ptr = MouseInfo.getPointerInfo();
rob.mouseMove((int) ptr.getLocation().getX() + 1, (int) ptr.getLocation().getY() + 1);
}
}
}
One simple way which i use to avoid "Windows desktop Auto lock" is "Switch On/Off NumLock" every 6 seconds.
Here a Java Program to Switch ON/OFF NumLock.
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class NumLock extends Thread {
public void run() {
try {
boolean flag = true;
do {
flag = !flag;
Thread.sleep(6000);
Toolkit.getDefaultToolkit().setLockingKeyState(KeyEvent. VK_NUM_LOCK, flag);
}
while(true);
}
catch(Exception e) {}
}
public static void main(String[] args) throws Exception {
new NumLock().start();
}
}
Run this Java program in a separate command prompt; :-)