Accessing 64-bit Registry in 32-bit application - java

Please do not mark this question as duplicate!
I'm searching for a solution in java - not C# - and used the WinRegistry class.
I wrote a program that can readout a registry key. Now the problem: the java application is 32bit and I want to read the reg-keys from a windows 7 64bit-system. With this code windows will redirect my 32bit program to the 32bit section of the 64bit-registry (compare the real path with the comment in the code - Wow6432Node!).
// only access to "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run"
value = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", "Citrix Login Service");
I deleted the try-catch-block so you are able to focus the real problem more better ;).

I solved this now - thanks goes to Petrucio who posted this solution in 2012: read/write to Windows Registry using Java.
E.g. - Read Operation:
try {
String value = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", "TestValue", WinRegistry.KEY_WOW64_64KEY);
System.out.println(value);
} catch (Exception ex) {
ex.printStackTrace();
}
I hope that is usefully for someone.

Related

Replace access to sun.misc.VM for JDK 11

In OpenJDK 8, it was possible to access sun.misc.VM and call isDirectMemoryPageAligned and maxDirectMemory.
isDirectMemoryPageAligned is used to size correctly the direct memory to allocate, as done by DirectByteBuffer.
maxDirectMemory is used to report memory statistics as well as access giving the value configured for -XX:MaxDirectMemorySize. Internally, it will set a limit to the allowed consumption of direct memory.
Since OpenJDK 9, the class VM has been moved to jdk.internal.misc and is not available unless --add-export java.base/jdk.internal.misc=xyz is used when running the application.
Is there a "right" way to do this ?
I already tried to use ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax() as a replacement for maxDirectMemory but it always returned -1 - meaning that the value was not available. It is also possible to access java.nio.Bits#MAX_MEMORY by reflection, but it remains "hackish".
Note that one could be very very dirty and do the following - working for OpenJDK, Zulu and Oracle 11.0.1 - but it is not the target goal of this question.
public static void tryExportInternal() {
final String moduleName = "jdk.internal.misc";
final Module javaLang = Integer.class.getModule();
// Method used only for tests by the JDK...
final Method exporter;
try {
exporter = Module.class.getDeclaredMethod("implAddExports", String.class);
exporter.setAccessible(true);
exporter.invoke(javaLang, moduleName);
} catch (NoSuchMethodException | IllegalAccessException e) {
LOG.log(Level.INFO, "Cannot access internal Module method", e);
} catch (InvocationTargetException e) {
LOG.log(Level.INFO, "Cannot call internal Module method", e);
}
}
In the source code, implAddExports is marked as #apiNote This method is for JDK tests only. :(
This answer comes from the various comments of Alan Bateman to the question.
No, there are no standard API to access the two wanted methods.
Since JDK 6, DirectxxxBuffers are not paged aligned anymore. Thus, accessing VM.isDirectMemoryPageAligned is not needed to reproduce what DirectBuffers do.
About manually memory allocation, being the use-case behind the question, the only API to do direct memory allocation is currently ByteBuffer.allocateDirect, or its JNI alternative NewDirectByteBuffer.
Comment references: 1 2 3

Java check if program is installed on windows

Is there a way to check if a specific program is installed on Windows using Java?
I'm trying to develop a Java program that automatically creates zip archives by using the code line command from 7-Zip.
So, I would like to check in Java if on my windows OS '7-Zip' is already installed. No check for running apps or if OS is Windows or Linux. I want to get a bool (true/false) if '7-Zip' is installed on Windows.
The library Apache Commons has a class called SystemUtils - full documentation is available at https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/SystemUtils.html.
In this library you have the following static boolean properties at your disposal:
SystemUtils.IS_OS_LINUX
SystemUtils.IS_OS_WINDOWS
The unix-like solution would be to simply try to run the program with --version flag (on windows probably the /? or - like in the 7zip case - without any at all) and check whether it fails, or what the return code will be.
Something like:
public boolean is7zipInstalled() {
try {
Process process = Runtime.getRuntime().exec("7zip.exe");
int code = process.waitFor();
return code == 0;
} catch (Exception e) {
return false;
}
}
I assume that you're talking about Windows. As Java is intended to be a platform-independent language and the way how to determine it differs per platform, there's no standard Java API to check that. You can however do it with help of JNI calls on a DLL which crawls the Windows registry. You can then just check if the registry key associated with the software is present in the registry. There's a 3rd party Java API with which you can crawl the Windows registry: jRegistryKey.
Here's an SSCCE with help of jRegistryKey:
package com.stackoverflow.q2439984;
import java.io.File;
import java.util.Iterator;
import ca.beq.util.win32.registry.RegistryKey;
import ca.beq.util.win32.registry.RootKey;
public class Test {
public static void main(String... args) throws Exception {
RegistryKey.initialize(Test.class.getResource("jRegistryKey.dll").getFile());
RegistryKey key = new RegistryKey(RootKey.HKLM, "Software\\Mozilla");
for (Iterator<RegistryKey> subkeys = key.subkeys(); subkeys.hasNext();) {
RegistryKey subkey = subkeys.next();
System.out.println(subkey.getName()); // You need to check here if there's anything which matches "Mozilla FireFox".
}
}
}
If you however intend to have a platformindependent application, then you'll also have to take into account the Linux/UNIX/Mac/Solaris/etc. (in other words: anywhere where Java is able to run) ways to detect whether FF is installed. Else you'll have to distribute it as a Windows-only application and do a System#exit() along with a warning whenever System.getProperty("os.name") is not Windows.
Sorry, I don't know how to detect in other platforms whether FF is installed or not, so don't expect an answer from me for that ;)

Java's "os.name" for Windows 10?

In Java, we can see the property value of os.name to know the name of the underlying operating system: System.getProperty("os.name").
For each edition of Windows, it used to return always the exact name of the OS: Windows XP for XP, Windows Vista for Vista, Windows 7 for Seven, Windows 8.1 for 8.1, and so on...
The problem is: I just updated my Windows 8.1 to Windows 10 using the released Microsoft updater, and it seems like this property still remains Windows 8.1:
public class OSTest {
public static void main(String[] args) {
System.out.println(System.getProperty("os.name"));
}
}
How can I create a workaround for this? And, does anyone know if this problem persists if installing a fresh Windows 10 copy - that is, this bug is caused by the Microsoft auto-updater -?
This is a known problem JDK-8066504 that has been fixed in upcoming Java 8 update 60.
The reason is GetVersionEx function has changed its behavior since Windows 8.1.
There are multiple possible workarounds, see MSDN article.
The trivial one is to exec cmd.exe /c ver.
The other is to look at the version information of one of the system files, e.g. kernel32.dll.
This is definitely a known bug. It occurs because the os.name property gets its value from the GetVersionEx in the source code of the Windows API. GetVersionEx however,
may be altered or unavailable for releases after Windows 8.1
As per Microsoft's official website. Instead, we will need to use the IsWindows10OrGreater found in the Version Helper API functions in the versionhelpers.h file. As you probably guessed though, this file is not a Java file, it is written in C. As a result we need to include it in a somewhat roundabout way. It does take quite a bit of work (you need to program in JNI :/) but this tutorial will help you do it. Another solution is shown in this bug log, and does require less effort.
I faced the same issue, used the following workaround:
The cmd command "systeminfo" returns "OS Name:" which is the right name for the OS, wrote the following function for this:
private boolean os2k10Check()
{
try{
Process p = Runtime.getRuntime().exec("systeminfo"); /*Execute cmd command "systeminfo"*/
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (true)
{
line = r.readLine();
if (line == null) { break; }
if(line.contains("OS Name:")) /*If output contains OS Name and 2010*/
{
if(line.contains("2010"))
return true;
else
return false;
}
}
}
catch(Exception e)
{System.out.println("Platform Type: os2010check: exception"+e);}
return false;
}
Hm... I don't know if it is a fix of Windows 10(10.0.17134.590) or of Java 8(1.8.0_171-b11 for me), but it is correct now: os.name gives me Windows 10.
Besides, if you don't trust it, you can check os.version. I have 10.0.
(By the way, I see os.arch:amd64. This is of JVM, not of OS. )
You could also use the .contains() method and just check for the "windows"
string maybe along the lines of
if (System.getProperty("os.name").toLowerCase().contains("windows") && System.getProperty("os.name").toLowerCase().contains(windows version here [xp, 7, 8, etc]))){}
If you need the windows version you could check for all versions and then assume 8.1 or 10 to move around the bug.
if (System.getProperty("os.name").toLowerCase().contains("windows") && System.getProperty("os.name").toLowerCase().contains("xp")){
//code for windows xp }
else if (System.getProperty("os.name").toLowerCase().contains("windows") && System.getProperty("os.name").toLowerCase().contains("vista")){
//code for windows vista
else if (System.getProperty("os.name").toLowerCase().contains("windows") && System.getProperty("os.name").toLowerCase().contains("7")){
//code for windows 7}
else if (System.getProperty("os.name").toLowerCase().contains("windows") && System.getProperty("os.name").toLowerCase().contains("8")){
//code for windows 8}
else if (System.getProperty("os.name").toLowerCase().contains("windows") && System.getProperty("os.name").toLowerCase().contains("8.1")){
//code for both windows 8.1 and 10
}
Now to explain what is going on here:
the if statement is just a conditional to determine the version of windows
The System.getProperty("os.name") returns the name of the os as a string
The .toLowerCase() method makes that returned String lower case
The .contains(String) method checks if the given input string is contained in the String it is being called on
The last statement allows for different code for each os except 8.1 & 10 which would need to be handled as one block :(

System-independent machine shutdown in Java [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Shutting down a computer using Java
I am making a personal program that will shut down my computer after a certain amount of time or at a certain time/date. However, I am running multiple operating systems and want to do this with one simple Java program. Is there any way to send a system-independent machine shutdown request in Java without any using any external libraries? I know you can use java.awt.Desktop.getDesktop().browse(new URI("shutdown /s")); in Windows, but, again, I want system independence.
No. There is not.
This is outside the scope of the JVM or standard Java class library.
Happy coding.
Why not use schedulers? All major operating systems supports such feature(cron, at etc). There may be other factors like permission which comes to play in modern windows (windows 7 ), linux etc.
If you want to really use some system call, Try using JNA. That simplifies platform specific access a lot.
#robjb gave me the best solution. Though it is a little too inflexible for my tastes, I will be suing it until I run into a problem.
String shutdownCommand;
StringPP operatingSystem = new StringPP(System.getProperty("os.name"));
if (operatingSystem.containsIgnoreCase("linux") ||
operatingSystem.containsIgnoreCase("mac") ||
operatingSystem.containsIgnoreCase("unix"))
{
shutdownCommand = "sudo shutdown -h -t 30";
}
else if (operatingSystem.containsIgnoreCase("windows"))
{
shutdownCommand = "shutdown /s /d P:0:0 /t 30 /c \"Blue Husky Timer 2 is shutting down your system, as you requested. \n"
+ "You have 30 seconds to save and close programs\"";
}
else
{
throw new UnsupportedOperationException("Unsupported operating system.");
}
try
{
Runtime.getRuntime().exec(shutdownCommand);
}
catch (Throwable t)
{
Main.LOG.logThrowable(t);
}
System.exit(0);
In the above example, StringPP is a custom class that augments the capabilities of a String with methods such as the above used #containsIgnoreCase. Main.LOG is a logging utility that I made and use.

NoClassDefFoundError while accessing GraphicsEnvironment.getLocalGraphicsEnvironment on Tomcat

I have an application which is running on tomcat, one of the methods is, creating a simple thumbnail from an jpeg image. The functions works fine offline and a week ago also on tomcat. But now i get the following error:
java.lang.NoClassDefFoundError
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:164)
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68)
java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1141)
eval.impl.ImageEval.getThumbnail(ImageEval.java:155)
eval.impl.ImageServlet.doGet(ImageServlet.java:79)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
I don't think that i have change anything what should influence this (actually i didn't change the function at all according to the svn repository), so it must be a library problem. But i can't figure out what is missing.
Here are the actual lines from the getThumbnail function, where the error occures:
BufferedImage thumbImage = new BufferedImage(thumbWidth,
thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(simage, 0, 0, thumbWidth, thumbHeight, null);
[edit] I decided to update the problem description a little.
Yes it seems that he can not find some class from java.awt or one related to that. But they do exist on the server in the jvm. Java headless mode doesn't solve the problem.
In another project the exact same code, but inside an axis2 webservice on this server is working fine.
[/edit]
It seems like you've change the configuration of Tomcat.
Either you've changed to a l{0,1}[iu]n[iu]x box or installed on a virtual machine with different security control than the one where you test it.
Apparently the
GraphicsEnvironment.getLocalGraphicsEnvironment()
Is trying to access the property: java.awt.graphicsenv
Which may return null or some non existing class name which is then loaded and throws the ClassNotFoundException. 1
The solution seems to be specifying the "java.awt.headless" property.
This is a similar question: java.awt.Color error
Try this search , it shows similar situations as your.
I remember there was something in the sun bugs database too.
Post the solution when you find it!
1.GraphicsEnvironment.java
EDIT
It is not eclipse!!
In my original post there is a link to the source code of the class which is throwing the exception.
Since I looks like you miss it, I'll post it here for you:
public static synchronized GraphicsEnvironment getLocalGraphicsEnvironment() {
if (localEnv == null) {
// Y O U R E R R O R O R I G I N A T E S H E R E !!!
String nm = (String) java.security.AccessController.doPrivileged
(new sun.security.action.GetPropertyAction
("java.awt.graphicsenv", null));
try {
// long t0 = System.currentTimeMillis();
localEnv =
(GraphicsEnvironment) Class.forName(nm).newInstance();
// long t1 = System.currentTimeMillis();
// System.out.println("GE creation took " + (t1-t0)+ "ms.");
if (isHeadless()) {
localEnv = new HeadlessGraphicsEnvironment(localEnv);
}
} catch (ClassNotFoundException e) {
throw new Error("Could not find class: "+nm);
} catch (InstantiationException e) {
throw new Error("Could not instantiate Graphics Environment: "
+ nm);
} catch (IllegalAccessException e) {
throw new Error ("Could not access Graphics Environment: "
+ nm);
}
}
return localEnv;
}
That's what gets executed.
And in the original post which you don't seem to have read, I said the code is accessing the property "java.awt.graphicsenv"
If that other project using axis doesn't have the same problem it may be because it may be running in a different tomcat configuration or the axis library allowed the access to that property. But we cannot be sure. That's pure speculation. So why don't you test the following and see what gets printed:
String nm = (String) java.security.AccessController.doPrivileged
(new sun.security.action.GetPropertyAction
("java.awt.graphicsenv", null));
System.out.println("java.awt.graphicsenv = " + nm );
It it prints null then you now what the problem is. You don't have that property in your system, or the security forbids you do use it.
It is very hard to tell you from here: "Go and edit file xyz and add : fail = false" So you have to do your work and try to figure out what's the real reason.
Start by researching what's the code being executed is ( which I have just posted ) and follow by understand what it does and how does all that "AccessController.doPrivileged" works. (You may use Google + StackOverflow for that).
We had a similar issue and after much trouble shooting it was identified to be related to the java.awt.headless property. The issue was resolved by explicitly setting the JVM option to
-Djava.awt.headless=true
It was running a week ago, and now it is not.
THEREFORE, YOU CHANGED SOMETHING BETWEEN "working" and "not working".
Go back to the working config (if you can), and rigorously track what you changed. If you don't have a backup of the working config, then meticulously go back through what you've done between working and non-working until you find what you changed.
It may not be code - it could be a config file, etc.
Best of luck,
-R
Is this server running java in server mode - I hear that doesn't load in the AWT classes.
If you are deploying this on *nix, and you don't have an X window system running anymore, that could explain it. Even if you do, if you aren't exporting the DISPLAY system variable to the process that starts the JVM, or if you are but it is not actually valid, it could cause such an issue.
That would at least explain why you didn't change any configuration in tomcat, but still have a problem.
If your NoClassDefFoundError has no message at all, then this means two things:
The JVM has already tried and failed to load a class. Usually, this means the JVM was unable to complete static initialization for that class, i.e. assign values to any static fields and run any static { } blocks. Often, this is because the classes necessary to do this static initialization are missing.
You're using Java 5, not Java 6. (In Java 6, you get a 'Could not initialize class xyz' message instead.)
The problem class appears to be the one whose name is the value of the system property java.awt.graphicsenv. I would start by finding out the value of this property. What happens when you try to instantiate this class?
Since you're getting NoClassDefFoundError from inside the AWT code, it looks like Java is failing to load the X Windows libraries. Note that even if you're running in headless mode ($DISPLAY not pointing to an X Windows server), AWT still needs some subset of the X11 libraries in order to render images. See, for example, this reference:
http://javatechniques.com/blog/linux-x11-libraries-for-headless-mode
If something stopped working and your Java code didn't change, it's possible that the X11 libraries got moved or uninstalled on your machine, or that for some other reason your LD_LIBRARY_PATH environment variable doesn't point to them anymore.

Categories

Resources