VisualVM: in my HeapDump String variables are always null - java

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.

Related

java getting concept of OOP right

hi guys I already searched a lot but weren't really satisfied with what I found. hope it's the right place to ask this question.
I'm doing Java now for a small amount of time (changed from C) and have problems of getting a grip of how to structure my code best for OOP.
let's give a simple example:
If I'm using some predefined strings (let's say e.g. filepaths or error messages) I'm currently creating an own class doing something like:
private static final String libPath = "\\this\\is\\a\\path\\";
private static final String notFoundMessage = "This hasn't been found";
public static String getLibPath() {
return libPath;
}
public static final String getNotFoundMessage() {
return notFoundMessage;
}
...
Would it be better to create a Map, add everything to it and get it by key?
Or am I doing it completely wrong?
Second example:
let's say I return an error string somewhere
public String getSomething() {
if (something != null) {
return something;
} else {
//handle error, return string below
}
return "I HAVE AN ERROR";
}
And anywhere else in my program I'm checking for the return value:
if (!string.equals("I HAVE AN ERROR")) {
//do something
}
else {
// handle error
}
that's obviously a bad way having to change the code twice once the error message changes. and yeah, I could define the error string the same way I'm doing it in the first example but as I'm not satisfied with that one either I'm reaching a dead end.
would be glad to hear some of your suggestions how to properly do OOP !
First example :
private static final String libPath = "\\this\\is\\a\\path\\";
private static final String notFoundMessage = "This hasn't been found";
public static String getLibPath() {
return libPath;
}
public static final String getNotFoundMessage() {
return notFoundMessage;
}
...
In this case, no need to create a Map. That is the right way to do it. Just note that the libPath would be better defined like this :
private static final Path libPath = Paths.get("this", "is", "a", "path");
(The class Path exists since Java 7, current version is Java 8)
Second example:
public String getSomething() {
if (something != null) {
return something;
} else {
//handle error, return string below
}
return "I HAVE AN ERROR";
}
No : Never return error codes in Java. Prefer using an exception.
Example :
public class ElementNotFoundException extends Exception {
...
}
public String getSomething() {
if (something == null) {
throw new ElementNotFoundException();
} else {
return something;
}
}
Then, you handle the exception like this :
try {
myObject.getSomething();
} catch(ElementNotFoundException e) {
//handle error
}
For the first example, take a look at Internationalization: http://docs.oracle.com/javase/tutorial/i18n/
You can use statics or maps, but sooner or later you will need to show the messages in several languages.
For the second example, it's better to use Exceptions as they are intended to be used when an abnormal condition (like an error) happens.
Anyway, with Exceptions take care not to use it as flow control structures: Why not use exceptions as regular flow of control?
Here are some examples for handling constants throug out your code:
1. Class
public final class MyConstants {
public static final int ERROR_CODE = -1;
}
if (getSomething() == MyConstants.ERROR_CODE) {
// ...
}
2. Interface
public interface MyConstantsHolder {
int ERROR_CODE = -1;
}
public MyClass implements MyConstantsHolder {
public void myMethod() {
if (getSomething() == ERROR_CODE) {
// ...
}
}
}

There are no main classes found

When I play it in NETBEANS IDE 8.0 it keeps saying there is no main class even though I added the main class already?
Need help can't understand.
PS. If I delete the static in magic() it blocks the magic() in main.
package fibotail;
import java.util.Scanner;
public class Fibotail {
public static int fibo(int control, int currentValue, int previousValue) {
if (control < 2) {
return currentValue;
}
return fibo(control - 1, currentValue + previousValue, currentValue);
}
public static void magic() {
String cCharacter;
do {
System.out.println("Input here: ");
int something = new Scanner(System.in).nextInt();
for (int i = 1; fibo(i, 0, 1) <= something; i++) {
System.out.println(fibo(i, 0, 1));
}
do {
System.out.println("Do you want to try again? ");
cCharacter = new Scanner(System.in).next();
} while (!(cCharacter.equals("y") || cCharacter.equals("Y") || cCharacter.equals("N") || cCharacter.equals("n")));
} while (cCharacter.equals('y') || cCharacter.equals('Y'));
}
public static int main(String args[]) {
magic();
return 0;
}
}
Return type should be void, not int:
public static void main(String args[]) { ... }
The JVM looks for the exact signature of the method.
When you run your project you would get:
Error: Main method must return a value of type void in class MainTest, please
define the main method as:
public static void main(String[] args)
In other languages than java, where main returns int (such as C and C++) the return code of main becomes the exit code of the process, which is often used by command interpreters and other external programs to determine whether the process completed successfully.
But java needs void as the return value. (Java internal architecture)
If you reaaly need to return a value just use the following:
System#exit(int)
To enable your program quit with a specific exit code which can be interpreted by the operating system.
Your main() method must have return type void
public static void main(String[] args){
}
Not int or other.
main() method is the entry point of your program and JVM is looking exact main() method.
You have to change your code a little bit. It should be:
public static void main(String args[])
The return type of main method is void

Check whether the cureent JVM is 64 bit or 32 bit

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.

Java: Use the same code with two different versions of a dependent class

Consider a Java class Foo that uses a library Bar. Foo should be distributed as a binary .class file and use the version of Bar that is already existing on a clients classpath.
There are two different versions of Bar that only differ in its method signatures. Foo should be compatible with both of them.
Example code:
public class Foo {
public static void main(String[] args){
Bar.librarycall("hello from foo");
//or
Bar.librarycall("hello from foo",1);
}
}
//v1
public class Bar {
public static void librarycall(String argument){
System.out.println("Bar1: " + argument);
}
}
//v2
public class Bar {
public static void librarycall(String argument,int i){
for(int j = 0; j < i; j++)
System.out.println("Bar2: " + argument);
}
}
I want to avoid reflection if possible. How would you propose to create a class Foo that is compatible with both versions of Bar?
[Edit]
This problem originates in a project I am working on. Bar corresponds to an external library I am using but cannot be modified for the code to work (I don't have the source code and the license doesn't allow modifications).
A refelective solution.
Class<?> c;
try {
c = Class.forName("Bar");
Method meths[] = c.getMethods();
Method v1method = null;
Method v2method = null;
for(Method m:meths) {
if(!m.getName().equals("librarycall")) continue;
if(!Modifier.isStatic(m.getModifiers())) {
System.out.println("Should be static");
continue;
}
Class<?> params[] = m.getParameterTypes();
if(params.length == 1 && params[0].equals(String.class) )
v1method = m;
if(params.length == 2 && params[0].equals(String.class) && params[1].equals(Integer.TYPE) )
v2method = m;
}
if(v2method!=null) {
v2method.invoke(null,"V2",5);
}
else if(v1method!=null) {
v1method.invoke(null,"V1");
}
else
System.out.println("No method found");
} catch (ClassNotFoundException e) {
System.out.println(e);
} catch (IllegalArgumentException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
You could use c = Bar.class; or if you already have an instance bar of Bar c = bar.getClass(). The invoke syntax is for static methods if its non static you need v1method.invoke(bar,"V1");.
Reflection does seem like the simplest way. The alternative would be to try calling the second version and catch a NoSuchMethodException.
public class Foo {
public static void main(String[] args){
try {
Bar.librarycall("hello from foo",1);
catch(NoSuchMethodException e) {
Bar.librarycall("hello from foo");
}
}
This is ugly, and slower, use Reflection its what its there for.
It sounds like this one task that is handled by the strategy pattern.
I'm assuming that:
You cannot change any of the versions of the Bar class files
You have the ability to write new Foo files
For some reason, you really want to avoid using Reflection
The two Bar files have the same package name
You may need to distribute two versions of the Foo class, as mentioned by JB Nizet in the comment to your question.

Why program is not allowing to initialize the static final variable?

I came across the Java code below which looks good at first but never compiles :
public class UnwelcomeGuest {
public static final long GUEST_USER_ID = -1;
private static final long USER_ID;
static {
try {
USER_ID = getUserIdFromEnvironment();
} catch (IdUnavailableException e) {
USER_ID = GUEST_USER_ID;
System.out.println("Logging in as guest");
}
}
private static long getUserIdFromEnvironment()
throws IdUnavailableException {
throw new IdUnavailableException(); // Simulate an error
}
public static void main(String[] args) {
System.out.println("User ID: " + USER_ID);
}
}//Class ends here
//User defined Exception
class IdUnavailableException extends Exception {
IdUnavailableException() { }
}//Class ends here
Below is the error message which comes in the IDE :
variable USER_ID might already have been assigned.
Is there any problem with the value assignment to the static final variable ?
Final variables allow at most one assignment in the constructor or the initializer block. The reason this does not compile is that Java code analyzer sees two assignments to USER_ID in branches that do not look mutually exclusive to it.
Working around this problem is simple:
static {
long theId;
try {
theId = getUserIdFromEnvironment();
} catch (IdUnavailableException e) {
theId = GUEST_USER_ID;
System.out.println("Logging in as guest");
}
USER_ID = theId;
}
The fact that you have used the assignment operator to throw the Exception in the following line:
USER_ID = getUserIdFromEnvironment();
means that the compiler thinks that there is a possibility of assignment, especially given the fact that it is declared as final.
Since the compiler gave you an that kind of error indicatesthat the variable has been creaated (and perhaps changed) somewhere else. It is good to change the name of your variable whereever it appears in your code.

Categories