Related
public void runKubernetes() {
KubernetesCluster k8sCluster = this.getKubernetesCluster("xyz-aks");
System.out.println("___________________________________________");
System.out.println("Kubernetes Cluster String: " + k8sCluster.name());
DefaultKubernetesClient kubeclient = new DefaultKubernetesClient();
System.out.println("Kube client Master URL :"+kubeclient.getMasterUrl());
NodeList kubenodes = kubeclient.nodes().list();
for (Node node : kubenodes.getItems()) {
System.out.println( node.getKind() + " => " + node.getMetadata().getName() +": " + node.getMetadata().getClusterName());
}
}
I get Client and nodes. Now, I have yaml file and I want to deploy that yaml (create service, deployment and pods) programatically.
I can do following
kubectl create -f pod-sample.yaml
but I want to do same thing using JAVA SDK.
I am using following java libraries for kubernetes:
io.fabric8.kubernetes
I believe you can parse the YAML or JSON of the deployment definition. For example, for YAML you can use any of the Java libraries here
JvYaml # Java port of RbYaml
SnakeYAML # Java 5 / YAML 1.1
YamlBeans # To/from JavaBeans
JYaml # Original Java Implementation
Camel # YAML 1.2 for Java. A user-friendly OOP library.
Jackson seems to be the more popular for JSON which also supports a YAML extension.
Then once you parse say the name, for example to create a service:
Service myservice = client.services().inNamespace(parsedNamespaceStr).createNew()
.withNewMetadata()
.withName(parsedServiceName)
.addToLabels(parsedLabel1, parseLabel2)
.endMetadata()
.done();
Is there a way to bypass the 32-bit java version (maybe a different way to start a proccess in VBA to invoke the 64-bit version cmd, turn off the UAC or some other sort of tweek) that is being "forced" by the following VBA code (this is just an assumption, I am explaining the debugging process below):
handleDbl = Shell("javaw -cp theJar.jar com.java.SampleClass", vbNormalFocus)
The main point here is that I want to share my macro and avoid putting extra instructions on the recipient so I am trying to do everything on the code (I am using late binding on VBA code to avoid to setting References manually and that kind of stuff).
Debugging Process
An error was thrown so I used the following line instead:
handleDbl = Shell("cmd /k java -cp theJar.jar com.java.SampleClass", vbNormalFocus)
And got the error Exception in thread "main" java.lang.UnsupportedClassVersionError: Unsupported major.minor version so I checked the java -version and tried to find out which java was running with:
C:\>where java
C:\Windows\System32\java.exe
C:\Program Files\Java\_anyJava.x.x.x_\bin\java.exe
I went to System32 folder and there was no java there but I knew that redirection happens from there to C:\Windows\SysWOW64 so I compared the previously extracted java version against C:\Windows\SysWOW64\java.exe -version and they matched.
After that I checked my Outlook version and turned out to be a 32-bit installation. That was a hint but it was mostly that and that big *32 next to the cmd.exe in the Task Manager. I don't know if a 64-bit Outlook would make a difference or it would be the same because of the VBA implementation but that's how I concluded the Shell function from VBA is causing 32-bit java call.
Normally there is a JAVA_HOME environment variable set. If so, then you can do something like this:
Dim JavaExe As String
JavaExe = """" & Environ("JAVA_HOME") & "\bin\java.exe"""
handleDbl = Shell("cmd /k " & JavaExe & " -cp theJar.jar com.java.SampleClass", vbNormalFocus)
If it isn't set, you'll have to find it by some searching, before compiling the command.
Sam's answer is great but I just felt uneasy about user going through more settings so I wrote some functions to check java's versions and notify the user if it is not there (would have to install java in that case anyway) so here is my code. It might contain some helpful stuff.
Private Function IsJavaAvailable(ByVal displayMessage As Boolean, Optional ByVal isJavaMandatory As Boolean) As Boolean
Dim availability As Boolean
Dim minJavaVersion As Integer
minJavaVersion = 8
'isJavaSetup is a global variable
If (Not isJavaSetup) Then
javawPathQuoted = GetMinimumJavaVersion(minJavaVersion)
If StrComp(javawPathQuoted, "") <> 0 Then
isJavaSetup = True
End If
SetGlobalVars
End If
If javawPathQuoted = Empty Then
availability = False
Else
availability = True
End If
If (displayMessage) Then
If (isJavaMandatory) Then
If Not availability Then
MsgBox "This functionality is NOT available without Java " & minJavaVersion & "." & _
vbNewLine & vbNewLine & _
"Please install Java " & minJavaVersion & " or higher.", vbCritical, _
"Mimimum Version Required: Java " & minJavaVersion
End If
Else
If Not availability Then
MsgBox "Some features of this functionality were disabled." & _
vbNewLine & vbNewLine & _
"Please install Java " & minJavaVersion & " or higher.", vbExclamation, _
"Mimimum Version Required: Java " & minJavaVersion
End If
End If
End If
IsJavaAvailable = availability
End Function
Private Function GetMinimumJavaVersion(ByVal javaMinimumMajorVersionInt As Integer) As String
'Run a shell command, returning the output as a string
Dim commandStr As String
Dim javawPathVar As Variant
Dim javaPathStr As Variant
Dim javaVersionStr As String
Dim javaMajorVersionInt As Integer
Dim detectedJavaPaths As Collection
Dim javaVersionElements As Collection
Dim javaVersionOutput As Collection
Dim detectedJavaVersions As Collection
Dim suitableJavawPath As String
'Check available javaw executables in the SO
commandStr = "where javaw"
Set detectedJavaPaths = GetCommandOutput(commandStr)
Set detectedJavaVersions = New Collection
For Each javawPathVar In detectedJavaPaths
'Look for java.exe instead of javaw.exe by substituting it in path
' javaw.exe does NOT return version output like java.exe
javaPathStr = StrReverse(Replace(StrReverse(javawPathVar), StrReverse("javaw.exe"), StrReverse("java.exe"), , 1))
commandStr = """" & javaPathStr & """" & " -version"
Set javaVersionOutput = GetCommandOutput(commandStr)
javaVersionStr = javaVersionOutput.item(1)
Debug.Print "Getting java version: ", commandStr
Debug.Print "Version detected: "; javaVersionStr
Set javaVersionElements = SplitOnDelimiter(javaVersionStr, " ")
'Check that output is not an error or something else
'java version "1.8.0_75"
If javaVersionElements.Count > 2 Then
If StrComp(javaVersionElements.item(1), "java", vbTextCompare) = 0 Then
If StrComp(javaVersionElements.item(2), "version", vbTextCompare) = 0 Then
detectedJavaVersions.Add javaVersionStr
'Remove quotes from "1.8.0_75", split on '.', get 2nd item (java major version) and cast it to Integer
javaMajorVersionInt = CInt(SplitOnDelimiter(SplitOnDelimiter(javaVersionElements.item(3), """").item(1), ".").item(2))
'JAR will only run in Java 8 or later
If (javaMajorVersionInt >= javaMinimumMajorVersionInt) Then
'Validate that "javaw.exe" exists since the validation was made with "java.exe"
Debug.Print "Verifying if javaw.exe exists: ", javawPathVar
If Len(Dir(javawPathVar)) > 0 Then
suitableJavawPath = javawPathVar
Debug.Print "A suitable javaw.exe version found: ", suitableJavawPath
Exit For
End If
End If
End If
End If
End If
Next javawPathVar
GetMinimumJavaVersion = suitableJavawPath
End Function
Private Function GetCommandOutput(ByRef commandStr As String) As Collection
'Run a shell command, returning the output as a string
Dim shellObj As Object
Set shellObj = CreateObject("WScript.Shell")
'run command
Dim wshScriptExecObj As Object
Dim stdOutObj As Object
Dim stdErrObj As Object
Set wshScriptExecObj = shellObj.Exec(commandStr)
Set stdOutObj = wshScriptExecObj.StdOut
Set stdErrObj = wshScriptExecObj.StdErr
'handle the results as they are written to and read from the StdOut object
Dim fullOutputCollection As Collection
Set fullOutputCollection = New Collection
Dim lineStr As String
While Not stdOutObj.AtEndOfStream
lineStr = stdOutObj.ReadLine
If lineStr <> "" Then
fullOutputCollection.Add lineStr
End If
Wend
If fullOutputCollection.Count = 0 Then
While Not stdErrObj.AtEndOfStream
lineStr = stdErrObj.ReadLine
If lineStr <> "" Then
fullOutputCollection.Add lineStr
End If
Wend
End If
Set GetCommandOutput = fullOutputCollection
End Function
I need to detect whether my application is running within a virtualized OS instance or not.
I've found an article with some useful information on the topic. The same article appears in multiple places, I'm unsure of the original source. VMware implements a particular invalid x86 instruction to return information about itself, while VirtualPC uses a magic number and I/O port with an IN instruction.
This is workable, but appears to be undocumented behavior in both cases. I suppose a future release of VMWare or VirtualPC might change the mechanism. Is there a better way? Is there a supported mechanism for either product?
Similarly, is there a way to detect Xen or VirtualBox?
I'm not concerned about cases where the platform is deliberately trying to hide itself. For example, honeypots use virtualization but sometimes obscure the mechanisms that malware would use to detect it. I don't care that my app would think it is not virtualized in these honeypots, I'm just looking for a "best effort" solution.
The application is mostly Java, though I'm expecting to use native code plus JNI for this particular function. Windows XP/Vista support is most important, though the mechanisms described in the referenced article are generic features of x86 and don't rely on any particular OS facility.
Have you heard about blue pill, red pill?. It's a technique used to see if you are running inside a virtual machine or not. The origin of the term stems from the matrix movie where Neo is offered a blue or a red pill (to stay inside the matrix = blue, or to enter the 'real' world = red).
The following is some code that will detect whether you are running inside 'the matrix' or not:
(code borrowed from this site which also contains some nice information about the topic at hand):
int swallow_redpill () {
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
return (m[5]>0xd0) ? 1 : 0;
}
The function will return 1 when you are running inside a virutal machine, and 0 otherwise.
Under Linux I used the command: dmidecode ( I have it both on CentOS and Ubuntu )
from the man:
dmidecode is a tool for dumping a
computer's DMI (some say SMBIOS) table
contents in a human-readable format.
So I searched the output and found out its probably Microsoft Hyper-V
Handle 0x0001, DMI type 1, 25 bytes
System Information
Manufacturer: Microsoft Corporation
Product Name: Virtual Machine
Version: 5.0
Serial Number: some-strings
UUID: some-strings
Wake-up Type: Power Switch
Handle 0x0002, DMI type 2, 8 bytes
Base Board Information
Manufacturer: Microsoft Corporation
Product Name: Virtual Machine
Version: 5.0
Serial Number: some-strings
Another way is to search to which manufacturer the MAC address of eth0 is related to: http://www.coffer.com/mac_find/
If it return Microsoft, vmware & etc.. then its probably a virtual server.
VMware has a Mechanisms to determine if software is running in a VMware virtual machine Knowledge base article which has some source code.
Microsoft also has a page on "Determining If Hypervisor Is Installed". MS spells out this requirement of a hypervisor in the IsVM TEST" section of their "Server Virtualization Validation Test" document
The VMware and MS docs both mention using the CPUID instruction to check the hypervisor-present bit (bit 31 of register ECX)
The RHEL bugtracker has one for "should set ISVM bit (ECX:31) for CPUID leaf 0x00000001" to set bit 31 of register ECX under the Xen kernel.
So without getting into vendor specifics it looks like you could use the CPUID check to know if you're running virtually or not.
No. This is impossible to detect with complete accuracy. Some virtualization systems, like QEMU, emulate an entire machine down to the hardware registers. Let's turn this around: what is it you're trying to do? Maybe we can help with that.
I think that going forward, relying on tricks like the broken SIDT virtualization is not really going to help as the hardware plugs all the holes that the weird and messy x86 architecture have left. The best would be to lobby the Vm providers for a standard way to tell that you are on a VM -- at least for the case when the user has explicitly allowed that. But if we assume that we are explicitly allowing the VM to be detected, we can just as well place visible markers in there, right? I would suggest just updating the disk on your VMs with a file telling you that you are on a VM -- a small text file in the root of the file system, for example. Or inspect the MAC of ETH0, and set that to a given known string.
On virtualbox, assuming you have control over the VM guest and you have dmidecode, you can use this command:
dmidecode -s bios-version
and it will return
VirtualBox
On linux systemd provides a command for detecting if the system is running as a virtual machine or not.
Command:
$ systemd-detect-virt
If the system is virtualized then it outputs name of the virtualization softwarwe/technology.
If not then it outputs none
For instance if the system is running KVM then:
$ systemd-detect-virt
kvm
You don't need to run it as sudo.
I'd like to recommend a paper posted on Usenix HotOS '07, Comptibility is Not Transparency: VMM Detection Myths and Realities, which concludes several techniques to tell whether the application is running in a virtualized environment.
For example, use sidt instruction as redpill does(but this instruction can also be made transparent by dynamic translation), or compare the runtime of cpuid against other non-virtualized instructions.
While installing the newes Ubuntu I discovered the package called imvirt. Have a look at it at http://micky.ibh.net/~liske/imvirt.html
This C function will detect VM Guest OS:
(Tested on Windows, compiled with Visual Studio)
#include <intrin.h>
bool isGuestOSVM()
{
unsigned int cpuInfo[4];
__cpuid((int*)cpuInfo,1);
return ((cpuInfo[2] >> 31) & 1) == 1;
}
Under Linux, you can report on /proc/cpuinfo. If it's in VMware, it usually comes-up differently than if it is on bare metal, but not always. Virtuozzo shows a pass-through to the underlying hardware.
Try by reading the SMBIOS structures, especially the structs with the BIOS information.
In Linux you can use the dmidecode utility to browse the information.
Check the tool virt-what. It uses previously mentioned dmidecode to determine if you are on a virtualized host and the type.
I Tried A Different approach suggested by my friend.Virtual Machines run on VMWARE doesnt have CPU TEMPERATURE property. i.e They Dont Show The Temperature of the CPU. I am using CPU Thermometer Application For Checking The CPU Temperature.
(Windows Running In VMWARE)
(Windows Running On A Real CPU)
So I Code a Small C Programme to detect the temperature Senser
#include "stdafx.h"
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
int main(int argc, char **argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t(L"SELECT * FROM Win32_TemperatureProbe"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"SystemName", 0, &vtProp, 0, 0);
wcout << " OS Name : " << vtProp.bstrVal << endl;
VariantClear(&vtProp);
VARIANT vtProp1;
VariantInit(&vtProp1);
pclsObj->Get(L"Caption", 0, &vtProp1, 0, 0);
wcout << "Caption: " << vtProp1.bstrVal << endl;
VariantClear(&vtProp1);
pclsObj->Release();
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
Output On a Vmware Machine
Output On A Real Cpu
I use this C# class to detect if the Guest OS is running inside a virtual environment (windows only):
sysInfo.cs
using System;
using System.Management;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
public class sysInfo
{
public static Boolean isVM()
{
bool foundMatch = false;
ManagementObjectSearcher search1 = new ManagementObjectSearcher("select * from Win32_BIOS");
var enu = search1.Get().GetEnumerator();
if (!enu.MoveNext()) throw new Exception("Unexpected WMI query failure");
string biosVersion = enu.Current["version"].ToString();
string biosSerialNumber = enu.Current["SerialNumber"].ToString();
try
{
foundMatch = Regex.IsMatch(biosVersion + " " + biosSerialNumber, "VMware|VIRTUAL|A M I|Xen", RegexOptions.IgnoreCase);
}
catch (ArgumentException ex)
{
// Syntax error in the regular expression
}
ManagementObjectSearcher search2 = new ManagementObjectSearcher("select * from Win32_ComputerSystem");
var enu2 = search2.Get().GetEnumerator();
if (!enu2.MoveNext()) throw new Exception("Unexpected WMI query failure");
string manufacturer = enu2.Current["manufacturer"].ToString();
string model = enu2.Current["model"].ToString();
try
{
foundMatch = Regex.IsMatch(manufacturer + " " + model, "Microsoft|VMWare|Virtual", RegexOptions.IgnoreCase);
}
catch (ArgumentException ex)
{
// Syntax error in the regular expression
}
return foundMatch;
}
}
}
Usage:
if (sysInfo.isVM()) {
Console.WriteLine("VM FOUND");
}
I came up with universal way to detect every type of windows virtual machine with just 1 line of code. It supports win7--10 (xp not tested yet).
Why we need universal way ?
Most common used way is to search and match vendor values from win32. But what if there are 1000+ VM manufacturers ? then you would have to write a code to match 1000+ VM signatures. But its time waste. Even after sometime, there would be new other VMs launched and your script would be wasted.
Background
I worked on it for many months. I done many tests upon which I observed that:
win32_portconnector always null and empty on VMs. Please see full report
//asked at: https://stackoverflow.com/q/64846900/14919621
what win32_portconnector is used for ? This question have 3 parts.
1) What is the use case of win32_portconnector ? //https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-portconnector
2) Can I get state of ports using it like Mouse cable, charger, HDMI cables etc ?
3) Why VM have null results on this query : Get-WmiObject Win32_PortConnector ?
On VM:
PS C:\Users\Administrator> Get-WmiObject Win32_PortConnector
On Real environment:
PS C:\Users\Administrator> Get-WmiObject Win32_PortConnector
Tag : Port Connector 0
ConnectorType : {23, 3}
SerialNumber :
ExternalReferenceDesignator :
PortType : 2
Tag : Port Connector 1
ConnectorType : {21, 2}
SerialNumber :
ExternalReferenceDesignator :
PortType : 9
Tag : Port Connector 2
ConnectorType : {64}
SerialNumber :
ExternalReferenceDesignator :
PortType : 16
Tag : Port Connector 3
ConnectorType : {22, 3}
SerialNumber :
ExternalReferenceDesignator :
PortType : 28
Tag : Port Connector 4
ConnectorType : {54}
SerialNumber :
ExternalReferenceDesignator :
PortType : 17
Tag : Port Connector 5
ConnectorType : {38}
SerialNumber :
ExternalReferenceDesignator :
PortType : 30
Tag : Port Connector 6
ConnectorType : {39}
SerialNumber :
ExternalReferenceDesignator :
PortType : 31
Show me Code
Based upon these tests, I have made an tiny program which can detect windows VMs.
//#graysuit
//https://graysuit.github.io
//https://github.com/Back-X/anti-vm
using System;
using System.Windows.Forms;
public class Universal_VM_Detector
{
static void Main()
{
if((new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_PortConnector")).Get().Count == 0)
{
MessageBox.Show("VM detected !");
}
else
{
MessageBox.Show("VM NOT detected !");
}
}
}
You can read code or get compiled executable.
Stability
It is tested on many environments and is very stable.
Detects Visrtualbox
Detects Vmware
Detects Windows Server
Detects RDP
Detects Virustotal
Detects any.run
etc...
I have a Perl script that uses Inline::Java and just has to fork (it is a server and I want it to handle multiple connections simultaneously).
So I wanted to implement this solution which makes use of a shared JVM with SHARED_JVM => 1. Since the JVM is not shutdown when the script exits, I want to reuse it with START_JVM => 0. But since it might just be the first time I start the server, I would also like to have a BEGIN block make sure a JVM is running before calling use Inline.
My question is very simple, but I couldn't find any answer on the web: How do I simply start a JVM? I've looked at man java and there seems to be just no option that means "start and just listen for connections".
Here is a simplified version of what I'm trying to do in Perl, if this helps:
BEGIN {
&start_jvm unless &jvm_is_running;
}
use Inline (
Java => 'STUDY',
SHARED_JVM => 1,
START_JVM => 0,
STUDY => ['JavaStuff'],
);
if (fork) {
JavaStuff->do_something;
wait;
}
else {
Inline::Java::reconnect_JVM();
JavaStuff->do_something;
}
What I need help with is writing the start_jvm subroutine.
If you've got a working jvm_is_running function, just use it to determine whether Inline::Java should start the JVM.
use Inline (
Java => 'STUDY',
SHARED_JVM => 1,
START_JVM => jvm_is_running() ? 0 : 1,
STUDY => ['JavaStuff'],
);
Thanks to details provided by tobyink, I am able to answer my own question, which was based on a the erroneous assumption that the JVM itself provides a server and a protocole.
As a matter of fact, one major component of Inline::Java is a server, written in Java, which handles request by the Inline::Java::JVM client, written in Perl.
Therefore, the command-line to launch the server is:
$ java org.perl.inline.java.InlineJavaServer <DEBUG> <HOST> <PORT> <SHARED_JVM> <PRIVATE> <NATIVE_DOUBLES>
where all parameters correspond to configuration options described in the Inline::Java documentation.
Therefore, in my case, the start_jvm subroutine would be:
sub start_jvm {
system
'java org.perl.inline.java.InlineJavaServer 0 localhost 7891 true false false';
}
(Not that it should be defined: tobyink's solution, while it did not directly address the question I asked, is much better.)
As for the jvm_is_running subroutine, this is how I defined it:
use Proc::ProcessTable;
use constant {
JAVA => 'java',
INLINE_SERVER => 'org.perl.inline.java.InlineJavaServer',
};
sub jvm_is_running {
my $pt = new Proc::ProcessTable;
return grep {
$_->fname eq JAVA && ( split /\s/, $_->cmndline )[1] eq INLINE_SERVER
} #{ $pt->table };
}
Goal: check java's version on a machine (I can get this from java -version). Compare it with latest available from java website
I would like to know if there is any way I can check for latest Java releases assuming that I have JRE/JDK installed on a machine.
If I can do this through Java itself, my solution would become platform independent. I could use java.net.URL class to send a request to Java website and get the HTML, however the response would be dynamic as Oracle can change their website and styles and possibly will have maintenance issues in long run.
I have looked at javatester.org, but I would not want it through an applet but through command line (which I can add to a script).
Through javacpl.exe, I can schedule periodic checks, but I would like to do it on demand.
The answer is actually quite simple. http://java.com/en/download/testjava.jsp issues a request to http://java.com/applet/JreCurrentVersion2.txt. That file currently contains a single version number: '1.7.0_11'...which is the latest and greatest, indeed.
Java code example
try (BufferedReader br = new BufferedReader(new InputStreamReader(new URL(
"http://java.com/applet/JreCurrentVersion2.txt").openStream()))) {
String fullVersion = br.readLine();
String version = fullVersion.split("_")[0];
String revision = fullVersion.split("_")[1];
System.out.println("Version " + version + " revision " + revision);
} catch (IOException e) {
// handle properly
}
Update 2014-03-20
Eventhough Java 8 was recently released http://java.com/applet/JreCurrentVersion2.txt currently still returns 1.7.0_51.
Update 2016-07-13
Looks like we need to come back to this every few months... Currently you need to scan http://java.com/en/download/installed8.jsp for a JavaScript variable latest8Version. So, you could run curl -s https://java.com/en/download/installed8.jsp | grep latest8Version.
Update 2018-08-19
http://javadl-esd-secure.oracle.com/update/baseline.version is another hot spot as mentioned in some other answer.
An URL very similar to the now defunct "JreCurrentVersion2.txt":
http://javadl-esd-secure.oracle.com/update/baseline.version
The contents of the link look like this:
1.8.0_111
1.7.0_121
1.6.0_131
1.5.0_99
1.4.2_43
You can easily parse the contents to find the latest JRE versions.
UPDATE: I don't recommend this method because this JRE is the one that has the Ask.com toolbar. You're better off downloading it yourself and distributing it yourself.
The jusched.exe program accesses the following URL to find out what versions are available. I think it's less likely to change because jusched is installed on millions of computers.
https://javadl-esd-secure.oracle.com/update/1.7.0/map-m-1.7.0.xml
Here is a snippet of what it returns for me:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
<java-update-map version="1.0">
<mapping>
<version>1.7.0_17</version>
<url>https://javadl-esd-secure.oracle.com/update/1.7.0/au-descriptor-1.7.0_25-b17.xml</url>
</mapping>
<mapping>
<version>1.7.0_21</version>
<url>https://javadl-esd-secure.oracle.com/update/1.7.0/au-descriptor-1.7.0_25-b17.xml</url>
</mapping>
</java-update-map>
To get the actual version that it is pointing to you have to fetch the above URL. Here is another snippet of what this XML looks like:
xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- XML file to be staged anywhere, and pointed to by map.xml file -->
<java-update>
<information version="1.0" xml:lang="en">
<caption>Java Update - Update Available</caption>
<title>Java Update Available</title>
<description>Java 7 Update 25 is ready to install. Installing Java 7 Update 25 might uninstall the latest Java 6 from your system. Click the Install button to update Java now. If you wish to update Java later, click the Later button.</description>
<moreinfo>http://java.com/moreinfolink</moreinfo>
<AlertTitle>Java Update Available</AlertTitle>
<AlertText>A new version of Java is ready to be installed.</AlertText>
<moreinfotxt>More information...</moreinfotxt>
<url>http://javadl.sun.com/webapps/download/GetFile/1.7.0_25-b17/windows-i586/jre-7u25-windows-i586-iftw.exe</url>
<version>1.7.0_25-b17</version>
<post-status>https://nometrics.java.com</post-status>
<cntry-lookup>http://rps-svcs.sun.com/services/countrylookup</cntry-lookup>
<predownload></predownload>
<options>/installmethod=jau FAMILYUPGRADE=1 SPWEB=http://javadl-esd.sun.com/update/1.7.0/sp-1.7.0_25-b17</options>
<urlinfo>24595ec7f861bc67e572f1e4ad3992441335e1a7</urlinfo>
</information>
</java-update>
The version tag contains the full version number.
You could parse the Java SE Downloads page to extract the Java versions.
That way, you get the version of both JDK6 and JDK7, which allows you to test your particular JDK (6 or 7) against the latest Oracle one.
(As opposed to the Free Java Download page, which only lists the JDK7)
Her is a crude script in Go, which you can compile on Windows, Unix, MacOs into a single independent executable, and use within a command line or a script:
package main
import (
"bytes"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"os/exec"
"regexp"
)
type Jdk struct {
Url string
Ver string
update string
}
func main() {
resp, err := http.Get("http://www.oracle.com/technetwork/java/javase/downloads/index.html")
if err != nil {
fmt.Printf("Error on http Get: %v\n", err)
return
}
bodyb, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("QueriesForOwner: error in ReadAll: %v\n", err)
return
}
br := bytes.NewBuffer(bodyb)
jdkre, err := regexp.Compile(`h3[^\r\n]+(/technetwork/java/javase/downloads/(jdk(?:6|7)(?:u(\d+))?)-downloads-\d+\.html)`)
if err != nil {
fmt.Printf("extract: error in regexp compilation: %v\n", err)
return
}
jdks := jdkre.FindAllSubmatch(br.Bytes(), -1)
jdk7 := Jdk{string(jdks[0][4]), string(jdks[0][5]), string(jdks[0][6])}
jdk6 := Jdk{string(jdks[1][7]), string(jdks[1][8]), string(jdks[1][9])}
fmt.Printf("Jdk7: %v\nJdk6: %v\n", jdk7, jdk6)
jver, err := exec.Command("java", "-version").CombinedOutput()
if err != nil {
fmt.Printf("*ExitError from java -version:", err)
return
}
fmt.Println("JVer: '", string(jver), "'")
jverre, err := regexp.Compile(`1.(\d).\d(?:_(\d+))"`)
jvers := jverre.FindSubmatch(jver)
jj := string(jvers[0])
jv := string(jvers[1])
ju := string(jvers[2])
jdk := jdk6
if jv == "7" {
jdk = jdk7
}
if jdk.update != ju {
fmt.Println("Local JDK *NOT* up-to-date: you have ", jj, ", Oracle has ", jdk.Ver)
} else {
fmt.Println("Local JDK *up-to-date*: you have ", jj, ", equals to Oracle, which has", jdk.Ver)
}
}
Again, this is a crude script, oriented toward JDK, and you would need to adapt it to your specific need, making its output and exit status match what you need for your script.
On my (PC) workstation, it returns:
Jdk7: {/technetwork/java/javase/downloads/jdk7u9-downloads-1859576.html jdk7u9 9}
Jdk6: {/technetwork/java/javase/downloads/jdk6u37-downloads-1859587.html jdk6u37 37}
JVer: ' java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b05)
Java HotSpot(TM) Client VM (build 20.6-b01, mixed mode, sharing)
'
Local JDK *NOT* up-to-date: you have 1.6.0_31" , Oracle has jdk6u37
I don't know what information you are exactly looking for, but you can get some version information using
System.getProperty("java.version");
If this is not what you're looking for, check the other available properties here:
http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#getProperties()
As for the latest available version, I guess you'd have to parse this site manually:
http://java.com/en/download/index.jsp
The latest version is on there, currently it's
Version 7 Update 9
You write that this is not what you want because "Oracle can change their website and styles". However, you want to find out the latest version of Java by accessing their service (website in this case). As long as you're not paying for this, they have no obligation to you, and can change the service whenever they want without your consent. And even when you're a paying customer, the best you can hope for is that they will inform you of upcoming changes, and your maintenance issues will remain.
Remember, it's THEIR service you want to use.
I have solved a similar issue some time ago with this groovy script (disclaimer: is somehow a "toy" script):
#Grapes([
#Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2.1')
])
def slurper = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser())
def url = new URL("http://www.java.com/download/manual.jsp")
def html
url.withReader { reader ->
html = slurper.parse(reader)
}
def lastJava = html.body.div.div.div.strong.text()
println "Last available java version: ${lastJava}"
println "Currently installed java version: ${System.properties["java.version"]}"
It yields something like:
Last available java version:
Version 7 Update 9
Currently installed java version: 1.7.0_07
If you want to avoid maintenance issues due to changes to the page structure, maybe a better option is to search for a line containing "Version x Update y".
To get all system variables
Properties properties = System.getProperties();
System.out.println(properties);
Sample output, this might be different in your system depending on your OS and Java JDK/JRE version.
{
java.runtime.name = Java(TM) SE Runtime Environment,
sun.boot.library.path = C:\Program Files\Java\jdk1.8.0_31\jre\bin,
java.vm.version = 25.31-b07,
java.vm.vendor = Oracle Corporation,
java.vendor.url = http://java.oracle.com/,
path.separator = ;,
idea.launcher.port = 7534,
java.vm.name = Java HotSpot(TM) 64-Bit Server VM,
file.encoding.pkg = sun.io,
user.country = NP,
user.script = ,
sun.java.launcher = SUN_STANDARD,
sun.os.patch.level = ,
java.vm.specification.name = Java Virtual Machine Specification,
user.dir = C:\Users\...\roid,
java.runtime.version = 1.8.0_31-b13,
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment,
java.endorsed.dirs = C:\Program Files\Java\jdk1.8.0_31\jre\lib\endorsed,
os.arch = amd64,
java.io.tmpdir = C:\Windows\TEMP\,
line.separator = ,
java.vm.specification.vendor = Oracle Corporation,
user.variant = ,
os.name = Windows 8.1,
sun.jnu.encoding = Cp1252,
java.library.path = C:\Program...roid,
java.specification.name = Java Platform API Specification,
java.class.version = 52.0,
sun.management.compiler = HotSpot 64-Bit Tiered Compilers,
os.version = 6.3,
user.home = C:\Users\Xxx,
user.timezone = Asia/Kathmandu,
java.awt.printerjob = sun.awt.windows.WPrinterJob,
file.encoding = UTF-8,
idea.launcher.bin.path = C:\Program Files (x86)\xxx\bin,
java.specification.version = 1.8,
java.class.path = C:\Program Files\Java\jdk1.8.0_31\jre\lib\charsets.jar;...,
user.name = Xxx,
java.vm.specification.version = 1.8,
sun.java.command = com.xxxx.ameras,
java.home = C:\Program Files\Java\jdk1.8.0_31\jre,
sun.arch.data.model = 64,
user.language = en,
java.specification.vendor = Oracle Corporation,
awt.toolkit = sun.awt.windows.WToolkit,
java.vm.info = mixed mode,
java.version = 1.8.0_31,
java.ext.dirs = C:\Program Files\Java\jdk1.8.0_31\jre\lib\ext;...,
java.vendor = Oracle Corporation,
file.separator = \,
java.vendor.url.bug = http://bugreport.sun.com/bugreport/,
sun.io.unicode.encoding = UnicodeLittle,
sun.cpu.endian = little,
sun.desktop = windows,
sun.cpu.isalist = amd64
}
Retrive only specific variable
String javaVersion = System.getProperty("java.version");
System.out.println(javaVersion);
Output
1.8.0_31
#MarcelStör's solution no longer works - the version in the file is 1.8.0_51, while the actual latest version is 1.8.0_91/92. If you go to the Java test page in Firefox or Chrome and open the development console you can get the variable latest8Version which currently is 1.8.0_91. This could be wrapped in a Selenium/Firefox solution, but is an incredibly hacky way of getting this information.
System.getProperty("java.vm.specification.version");
System.getProperty("java.version");