After some research on the same topic, I used the method "getVersion()" to check whether a JVM is 64 bit or 32 bit.
public static String getVersion()
{
String version = System.getProperty("sun.arch.data.model");
if (version != null && version.contains("64")){
return "64";
}else{
return "32";
}
}
It went wrong in some cases. Yes as the flag name mentions, the method is clearly sun-dependent. I tried getting the property "os.arch" also. But in some cases, it is wrongly identifying JVM.
Is there any more trustable way of checking the same?
My application is purely based on windows. And I don't want the method to work on any other platforms.
Here is a pure Java solution that checks the ability to link 32-bit library into the current process:
static boolean is64bitProcess() {
String wow64_kernel = System.getenv("systemroot") + "\\SysWOW64\\kernel32.dll";
if (new File(wow64_kernel).exists()) {
try {
System.load(wow64_kernel);
} catch (UnsatisfiedLinkError e) {
return true; // can not link 32-bit library into 64-bit process
}
}
return false;
}
You will need the 2 jar files from here :
https://java.net/projects/jna/downloads/directory/3.3.0
(Code edited to fix evaluation of IsWow64Process)
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;
public class Main {
public static void main(String[] args) {
System.out.println(is64BitJava());
}
private static boolean is64BitJava(){
if (!is64BitWindows()){
return false;
}
Kernel32 kernel32 = Kernel32.INSTANCE;
WinNT.HANDLE handle = kernel32.GetCurrentProcess();
if (!kernel32.IsWow64Process(handle, ref)){
return false;
}
return ref.getValue() == 0;
}
private static boolean is64BitWindows(){
String envVar = System.getenv("ProgramW6432");
if (envVar == null){
envVar = "";
}
return envVar.length() > 0;
}
}
In order to check if Windows is 64 bit, I check if ProgramW6432 environment variable is defined.
Then I use Win32 API GetCurrentProcess and IsWow64Process functions to examine current running process.
Related
I have an application that shows a JavaFX/OpenJFX FileChooser, when the user chooses a file it should appear in the OS recent files list, but it doesn't happen.
How could I create a symlink or add the file to the OS recent files?
Thanks.
This answer covers the Windows part so far, and hopefully, this becomes a collaborative answer and somebody else fills up the missing parts for macOS and Unix:
Main Structure:
public interface RecentDocsSaver {
void addToRecentDocs(File file);
}
public class RecentDocsSaverFactory {
private static final String OS_NAME = System.getProperty("os.name").toLowerCase();
private RecentDocsSaverFactory() {
}
public static RecentDocsSaver getOSInstance() {
if (isWindows()) {
return WindowsRecentDocsSaver.INSTANCE;
}
// TODO: add code for mac and unix
throw new UnsupportedOperationException(OS_NAME + " is not supported");
}
private static boolean isWindows() {
return OS_NAME.contains("win");
}
private static boolean isMac() {
return OS_NAME.contains("mac");
}
private static boolean isUnix() {
return OS_NAME.contains("nix") || OS_NAME.contains("nux") || OS_NAME.contains("aix");
}
}
Windows:
I believe using JNA is the correct way to add files to Windows's recent list (other ways include accessing Windows registry).
The Shell32 library provides a function to add files directly to the recent files list. The function is SHAddToRecentDocs(flags, path).
public class WindowsRecentDocsSaver implements RecentDocsSaver {
public static final WindowsRecentDocsSaver INSTANCE = new WindowsRecentDocsSaver();
private WindowsRecentDocsSaver() {
}
public void addToRecentDocs(File file) {
if (file != null) {
WString unicodeStringPath = new WString(file.getPath());
// 3 is for null-terminated Unicode string
Shell32.INSTANCE.SHAddToRecentDocs(3, unicodeStringPath);
}
}
private interface Shell32 extends ShellAPI {
Shell32 INSTANCE = Native.loadLibrary("shell32", Shell32.class);
void SHAddToRecentDocs(int flags, WString file);
}
}
macOS: TODO
Unix: TODO
Usage:
File recent = fileChooser.showOpenDialog(window);
if (recent != null) {
RecentDocsSaverFactory.getOSInstance().addToRecentDocs(recent);
}
My application returns unsupported using the cn1-codescan.cn1lib. When I use the deprecated CodeScanner (com.codename1.codescan.*) the scanner application works but a value is never returned. I'm testing on a Samsung Note 4, in case that might make a difference...
private void scanIt(TextField tfField)
{
if(CodeScanner.isSupported())
{
CodeScanner cs = CodeScanner.getInstance();
if(cs != null)
{
MyScanResult msr = new MyScanResult();
cs.scanBarCode(msr);
tfField.setText(msr.scancode);
}
else
tfField.setText("No Instance!");
}
else
tfField.setText("Not Supported!");
}
import com.codename1.ext.codescan.*;
public class MyScanResult implements ScanResult
{
public String scancode = null;
public MyScanResult()
{
}
public void scanCompleted(String contents, String formatName, byte[] rawBytes)
{
scancode = contents;
}
public void scanCanceled()
{
scancode = "Canceled";
}
public void scanError(int errorCode, String message)
{
scancode = "Error! "+message;
}
}
These are the two relevant function calls. I appreciate your help in advance. Thank-you.
When using a deprecated API you can point your IDE on the deprecated feature to get additional help and in most cases the deprecation is explained and the class you should use is mentioned in the deprecation notice.
You specifically used com.codename1.codescan.CodeScanner which is the old no longer working implementation. You should have used com.codename1.ext.codescan.CodeScanner which isn't deprecated and should work fine. It will be there only if the cn1lib is installed and refreshed.
This question already has an answer here:
is it is possible to disable the windows keys using java
(1 answer)
Closed 6 years ago.
I am trying to make a small application, similar to a cyber cafe software.
To be specific, what i want to do is that once the app starts, you can't do anything in the computer, and it's impossible to cease the locking, (Alt + F4, Ctrl + Alt + Del, Task Manager, etc.) unless you put up a certain username and password, and once a specific amount of time has passed by, the software will lock the computer again.
I am pretty much a novice in Java, so i couldn't find any answers that i could understand or that were what i was looking for. Is this possible to do?
Thanks in advance!
You'd probably need to use JNA to do things like that, or just change to C++/C#.
Such example as this:
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.KBDLLHOOKSTRUCT;
import com.sun.jna.platform.win32.WinUser.LowLevelKeyboardProc;
import com.sun.jna.platform.win32.WinUser.MSG;
public class KeyHook {
private static HHOOK hhk;
private static LowLevelKeyboardProc keyboardHook;
private static User32 lib;
public static void blockWindowsKey() {
if (isWindows()) {
new Thread(new Runnable() {
#Override
public void run() {
lib = User32.INSTANCE;
HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
keyboardHook = new LowLevelKeyboardProc() {
public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
if (nCode >= 0) {
switch (info.vkCode){
case 0x5B: //Around here would be where you add all your 0x key codes
case 0x5C:
return new LRESULT(1);
default: //do nothing
}
}
return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
}
};
hhk = lib.SetWindowsHookEx(13, keyboardHook, hMod, 0);
// This bit never returns from GetMessage
int result;
MSG msg = new MSG();
while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
if (result == -1) {
break;
} else {
lib.TranslateMessage(msg);
lib.DispatchMessage(msg);
}
}
lib.UnhookWindowsHookEx(hhk);
}
}).start();
}
}
public static void unblockWindowsKey() {
if (isWindows() && lib != null) {
lib.UnhookWindowsHookEx(hhk);
}
}
public static boolean isWindows(){
String os = System.getProperty("os.name").toLowerCase();
return (os.indexOf( "win" ) >= 0);
}
}
(That was not mine, ill explain in a bit)
Then see if it is running Windows by 'KeyHook.isWindows()'.
If it is, use things like 'blockWindowsKey()' or make your own functions like it. I put a comment where you'd change the key code.
FYI possible duplicate of is it is possible to disable the windows keys using java
Thats where the code came from.
I have coded a simple program to understand how VisualVM works. Here is the full code:
package memorygames;
public class MemoryGames
{
static class A {
private int i;
private String s;
A(int i, String s)
{
this.i = i;
this.s = s;
}
public int getI()
{
return i;
}
public String getS()
{
return s;
}
}
public static void main(String[] args) {
A a = new A(23, "hello");
while(true) {
System.out.println(a.getS());
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
Now I make a HeapDump of my application in VisualVM. I see the instance of my 'A' class, but the s variable is empty! Its value equal to null. 'i' variable holds the correct value of 23.
Why this happens?
UPDATE:
May be I am misusing the VisualVM? Here is my screenshot:
http://oi42.tinypic.com/2091qfl.jpg
UPDATE:
Not sure, but probably this was a result of some memory optimization. I have added
while(true) {
a.setS(new String("a-setter " + Math.random()));
(...)
}
... and now I can see the string value in the variable. I wonder do other people could really see the results in the Heap different from mine.
It could be a problem of the JDK you are using to run your example. Can you try different version of JDK? JDK 7u40 or JDK 8 preview build? It works for me using JDK 7u40.
How can I make an option accept only some specified values like in the following example:
$ java -jar Mumu.jar -a foo
OK
$ java -jar Mumu.jar -a bar
OK
$ java -jar Mumu.jar -a foobar
foobar is not a valid value for -a
Since commons-cli doesn't support that directly, the simplest solution is probably to check the value of an option when you get it.
The other way can be to extend the Option class. At work we have made that:
public static class ChoiceOption extends Option {
private final String[] choices;
public ChoiceOption(
final String opt,
final String longOpt,
final boolean hasArg,
final String description,
final String... choices) throws IllegalArgumentException {
super(opt, longOpt, hasArg, description + ' ' + Arrays.toString(choices));
this.choices = choices;
}
public String getChoiceValue() throws RuntimeException {
final String value = super.getValue();
if (value == null) {
return value;
}
if (ArrayUtils.contains(choices, value)) {
return value;
}
throw new RuntimeException( value " + describe(this) + " should be one of " + Arrays.toString(choices));
}
#Override
public boolean equals(final Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
return new EqualsBuilder().appendSuper(super.equals(o))
.append(choices, ((ChoiceOption) o).choices)
.isEquals();
}
#Override
public int hashCode() {
return new ashCodeBuilder().appendSuper(super.hashCode()).append(choices).toHashCode();
}
}
I've wanted this kind of behaviour before, and never came across a way to do this with an already provided method. That's not to say it doesn't exist. A kind of lame way, is to add the code yourself such as:
private void checkSuitableValue(CommandLine line) {
if(line.hasOption("a")) {
String value = line.getOptionValue("a");
if("foo".equals(value)) {
println("OK");
} else if("bar".equals(value)) {
println("OK");
} else {
println(value + "is not a valid value for -a");
System.exit(1);
}
}
}
Obviously there would be nicer ways to do this than the long if/else, possibly with an enum, but that should be all you'd need. Also I've not compiled this, but I reckon it should work.
This example also does not make the "-a" switch mandatory, since that wasn't specified in the question.