A way to get all objects instances from JVM memory - java

Is there a way to get all objects instances from JVM memory and print its' toString() representation in file?
I need to do a shot of all my app's objects instances in moment of error.
I think dump is not what I looking for because it doesn't give me precise information about what instances were contained in memory at the moment, only statictics information.

What you are asking for is essentially called heap dump.
Heapdump is a snapshot of JVM memory in a given time, it contains info about all the objects.
To capture it you can do
jmap -dump:format=b,file=heap.bin <pid>
pid: id of the Java process
There are several tools that can analyze the file outputted. Good change is that your IDE can do it, that way you can view it in familiar interface.
More here
https://dzone.com/articles/java-heap-dump-analyzer-1
To programatically trigger hepdump you can do something like this
public class HeapDumper {
private static final String HOTSPOT_BEAN_NAME =
"com.sun.management:type=HotSpotDiagnostic";
private static volatile HotSpotDiagnosticMXBean hotspotMBean;
static void dumpHeap(String fileName, boolean live) {
initHotspotMBean();
try {
hotspotMBean.dumpHeap(fileName, live);
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
private static void initHotspotMBean() {
if (hotspotMBean == null) {
synchronized (HeapDumper.class) {
if (hotspotMBean == null) {
hotspotMBean = getHotspotMBean();
}
}
}
}
private static HotSpotDiagnosticMXBean getHotspotMBean() {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean bean =
ManagementFactory.newPlatformMXBeanProxy(server,
HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
return bean;
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
}
Triggering it like this
String fileName = "heap.bin";
boolean live = true; // only reachable object - true, all objects - false
dumpHeap(fileName, live);

Related

Dead code warning in try-with-resources, but not in translated try-catch-finally

The following code uses the try-with-resources construction introduced in Java 8. The occasionallyThrow() method is declared to throw an OccasionalException, the Resource's close() method to throw a CloseException. Eclipse (Version: Neon Release (4.6.0), Build id: 20160613-1800) adds a warning on the line marked with // dead code that the branch is dead code. Implicitly, Eclipse affirms that the line marked with // alive code is not dead code.
Object tryWithResources() throws OccasionalException {
Object value = null;
try (Resource resource = new Resource()) {
occasionallyThrow();
value = new Object();
}
catch (CloseException e) {
if (value == null) {
// alive code
}
else {
// dead code
}
}
return value;
}
I'm confused by this. If occasionallyThrow() throws its OccasionalException, then the try-with-resources should catch that as the primary exception and then attempt to close the resource. If closing the resource throws a CloseException, then it will be suppressed under the OccasionalException, so there won't be the CloseException to catch. So, the only time there should be CloseException to catch is when the block within the try completed successfully which means that value is non-null. So it seems like the "dead code" is actually alive, and the "alive code" is actually dead. I'm not sure what a compiler is actually expected to recognize here, but at the very least, it seems like the "dead code" here should not be called dead.
What makes this more complicated is that the translated form without using the try-with-resources form doesn't get marked with any dead code warnings at all. (I'm fairly confident that I got this translation right, based on 14.20.3.2. Extended try-with-resources, but I wouldn't be completely surprised if there's bug hereā€¦)
Object expandedTry() throws OccasionalException {
Object value = null;
try {
Resource resource = new Resource();
Throwable $primary = null;
try {
occasionallyThrow();
value = new Object();
}
catch (Throwable t) {
$primary = t;
throw t;
}
finally {
if (resource != null) {
if ($primary != null) {
try {
resource.close();
}
catch (Throwable $suppressed) {
$primary.addSuppressed($suppressed);
}
}
else {
resource.close();
}
}
}
}
catch (CloseException e) {
if (value == null) {
// alive (not dead!)
}
else {
// alive
}
}
return value;
}
Am I missing something that would make either branch in the if-else dead in one of these, but not in the other?
Full Code
Here's the full code with definitions of the auxiliary exception types, the Resource class, and the top-level class.
public class TestTryWithResources {
/** Exception thrown by Resource's close() method */
#SuppressWarnings("serial")
static class CloseException extends Exception {}
/** AutoCloseable declared to throw a CloseException */
static class Resource implements AutoCloseable {
#Override
public void close() throws CloseException {}
}
/** An occasionally thrown exception */
#SuppressWarnings("serial")
static class OccasionalException extends Exception {}
/** Method declared to throw an occasional exception */
void occasionallyThrow() throws OccasionalException {}
/*
* Method using try-with-resources. Eclipse warns that the
* portion marked with "// dead code" is Dead code.
*/
Object tryWithResources() throws OccasionalException {
Object value = null;
try (Resource resource = new Resource()) {
occasionallyThrow();
value = new Object();
}
catch (CloseException e) {
if (value == null) {
// alive code
}
else {
// dead code
}
}
return value;
}
/*
* Method not using try-with-resources. This is the translation
* of the try-with-resources in tryWithResources, according to
* [14.20.3 try-with-resources][1]. Eclipse does not warn about
* any of the code being Dead code.
*
* [1]: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3
*/
Object expandedTry() throws OccasionalException {
Object value = null;
try {
Resource resource = new Resource();
Throwable $primary = null;
try {
occasionallyThrow();
value = new Object();
}
catch (Throwable t) {
$primary = t;
throw t;
}
finally {
if (resource != null) {
if ($primary != null) {
try {
resource.close();
}
catch (Throwable $suppressed) {
$primary.addSuppressed($suppressed);
}
}
else {
resource.close();
}
}
}
}
catch (CloseException e) {
if (value == null) {
// alive
}
else {
// alive
}
}
return value;
}
}
Responses to Comments
Amin J's answer suggested a workaround of using the resource after setting value to change Eclipse's code analysis. This doesn't work though. After using the resource, e.g., by printing it, the dead code warning is still present in both Luna and Neon:
For some reason the static code analyzer thinks that that the resource is going to be closed right after the try declaration while according to this tutorial the resource is closed after the statement.
The try-with-resources statement ensures that each resource is closed at the end of the statement.
So for instance if you change your code to use the resource after value is is (code below) it won't warn you about the dead code (tested on Eclipse Luna however).
Object tryWithResources() throws OccasionalException {
Object value = null;
try (Resource resource = new Resource()) {
occasionallyThrow();
value = new Object();
resource.someMethod(); // using the resource, so eclipse thinks it's not closed yet (correctly)
}
catch (CloseException e) {
if (value == null) {
// alive code
}
else {
// dead code
}
}
return value;
}
UPDATE
This is the actual code I tested with usage of resource (in this case reader) after setting the value.
Object val = null;
try (BufferedReader reader = new BufferedReader(new FileReader("C:\\file.txt"))) {
val = new Object();
System.out.println("got here");
reader.readLine();
}
catch(IOException e){
System.out.println("io ex");
if ( val == null){
}
else{
}
}
This doesn't answer the question of why Eclipse is generating the warning that it is, or whether it should be or not, but this is a workaround that at least eliminates the warning for the time being. Rather than putting the conditional in the catch block, you can call another method with the value being tested as well as a the exception, and from that method test whether the object is null and then do whatever needs to be done:
Object tryWithResources() throws OccasionalException {
Object value = null;
try (Resource resource = new Resource()) {
occasionallyThrow();
value = new Object();
System.out.println(resource.toString());
}
catch (CloseException e) {
catchBlock(value, e); // call auxiliary method
}
return value;
}
void catchBlock(Object value, CloseException e) {
if (value == null) {
// then
}
else {
// else
}
}

Unexpected output in concurrent file writing in java web

I wrote a very simple Java web application ,just included some basic function like register , sign in , changing the password and some others.
I don't use database. I just create a file in the app to record the users' information and do the database stuff.
I used JMeter to stressing the web application, especially the register interface.
The JMeter shows that the result of the 1000 thread is right
but when I look into the information.txt , which stores the users' information, it's wrong because it stores 700+ record :
but it should include 1000 record, it must be somewhere wrong
I use the singleton class to do the write/read stuff, and i add a synchronized word to the class, the insert() function which is used by register to record the register information is shown as below: (a part of it)
public class Database {
private static Database database = null;
private static File file = null;
public synchronized static Database getInstance() {
if (database == null) {
database = new Database();
}
return database;
}
private Database() {
String path = this.getClass().getClassLoader().getResource("/")
.getPath() + "information.txt";
file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public void insert(String account, String password, String username) {
RandomAccessFile infoFile = null;
try {
infoFile = new RandomAccessFile(file, "rw");
String record;
long offset = 0;
while ((record = infoFile.readLine()) != null ) {
offset += record.getBytes().length+2;
}
infoFile.seek(offset);
record = account+"|"+password+"|"+username+"\r\n";
infoFile.write(record.getBytes());
infoFile.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (infoFile != null) {
try {
infoFile.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
the question is why would this happened , the synchronized is thread safe, why i lost so many data and some blank line was inserted into it, what could I do the correct it !
You are synchronizing the getInstance() method, but not the insert() method. This makes the retrieval of the instance of Database thread-safe, but not the write operation.

How do I save states to a file and keep the file safe?

I'm trying to create save states for my game, not so much for where your game was left but something simple like score boards. The format would be something like this:
Wins: 5
Losses: 10
GamesPlayed: 15
I need to be able to access the file, and depending on whether the player won/lost it will append +1 to the value in the file.
What would be the best way to go about this? I've heard of a bunch of different ways to save data, for example XML, but aren't those overkill for the size of my data?
Also, I do want to keep this file safe from the users being able to go into the files and change the data. Would I have to do some sort of encryption? And, if the user removes the file and replaces it with an empty one can't they technically reset their values?
You can use plain serialization/deserialization for this. In order to serialize/deserialize a class, it must implement the Serializable interface. Here's a example to start with:
public class Score implements Serializable {
private int wins;
private int loses;
private int gamesPlayed;
//constructor, getter and setters...
}
public class ScoreDataHandler {
private static final String fileName = "score.dat";
public void saveScore(Score score) {
ObjectOutputStreamout = null;
try {
out = new ObjectOutputStream(new FileOutputStream(fileName));
out.writeObject(score);
} catch (Exception e) {
//handle your exceptions...
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
}
}
}
}
public Score loadScore() {
ObjectInputStreamin = null;
Score score = null;
try {
in = new ObjectInputStream(new FileInputStream(fileName));
score = (Score)in.readObject();
} catch (Exception e) {
//handle your exceptions...
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ioe) {
}
}
}
return score;
}
}

Telling a ThreadPoolExecutor when it should go ahead or not

I have to send a set of files to several computers through a certain port. The fact is that, each time that the method that sends the files is called, the destination data (address and port) is calculated. Therefore, using a loop that creates a thread for each method call, and surround the method call with a try-catch statement for a BindException to process the situation of the program trying to use a port which is already in use (different destination addresses may receive the message through the same port) telling the thread to wait some seconds and then restart to retry, and keep trying until the exception is not thrown (the shipping is successfully performed).
I didn't know why (although I could guess it when I first saw it), Netbeans warned me about that sleeping a Thread object inside a loop is not the best choice. Then I googled a bit for further information and found this link to another stackoverflow post, which looked so interesting (I had never heard of the ThreadPoolExecutor class). I've been reading both that link and the API in order to try to improve my program, but I'm not yet pretty sure about how am I supposed to apply that in my program. Could anybody give a helping hand on this please?
EDIT: The important code:
for (Iterator<String> it = ConnectionsPanel.list.getSelectedValuesList().iterator(); it.hasNext();) {
final String x = it.next();
new Thread() {
#Override
public void run() {
ConnectionsPanel.singleAddVideos(x);
}
}.start();
}
private static void singleAddVideos(String connName) {
String newVideosInfo = "";
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
newVideosInfo = newVideosInfo.concat(it.next().toString());
}
try {
MassiveDesktopClient.sendMessage("hi", connName);
if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
MassiveDesktopClient.sendMessage(newVideosInfo, connName);
}
} catch (BindException ex) {
MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
try {
Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
} catch (InterruptedException ex1) {
JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
}
ConnectionsPanel.singleAddVideos(connName);
return;
}
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
try {
MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
} catch (BindException ex) {
MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
try {
Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
} catch (InterruptedException ex1) {
JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
}
ConnectionsPanel.singleAddVideos(connName);
return;
}
}
}
Your question is not very clear - I understand that you want to rerun your task until it succeeds (no BindException). To do that, you could:
try to run your code without catching the exception
capture the exception from the future
reschedule the task a bit later if it fails
A simplified code would be as below - add error messages and refine as needed:
public static void main(String[] args) throws Exception {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(corePoolSize);
final String x = "video";
Callable<Void> yourTask = new Callable<Void>() {
#Override
public Void call() throws BindException {
ConnectionsPanel.singleAddVideos(x);
return null;
}
};
Future f = scheduler.submit(yourTask);
boolean added = false; //it will retry until success
//you might use an int instead to retry
//n times only and avoid the risk of infinite loop
while (!added) {
try {
f.get();
added = true; //added set to true if no exception caught
} catch (ExecutionException e) {
if (e.getCause() instanceof BindException) {
scheduler.schedule(yourTask, 3, TimeUnit.SECONDS); //reschedule in 3 seconds
} else {
//another exception was thrown => handle it
}
}
}
}
public static class ConnectionsPanel {
private static void singleAddVideos(String connName) throws BindException {
String newVideosInfo = "";
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
newVideosInfo = newVideosInfo.concat(it.next().toString());
}
MassiveDesktopClient.sendMessage("hi", connName);
if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
MassiveDesktopClient.sendMessage(newVideosInfo, connName);
}
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
}
}
}

Find the directory for a FileStore

I'm trying to find a way to detect when a flash drive has been plugged into my computer. So far, the solution I found was to poll FileSystem#getFileStores for changes. This does indeed tell me when the flash drive has been inserted, but as far as I can tell there is no way to retrieve the location for it. FileStore#type and FileStore#name both seem highly unreliable as their return value is implementation specific, but they appear to be the only methods that might return any relevant information that might help find the directory for the FileStore.
With that in mind, the following code:
public class Test {
public static void main(String[] args) throws IOException {
for (FileStore store : FileSystems.getDefault().getFileStores()) {
System.out.println(store);
System.out.println("\t" + store.name());
System.out.println("\t" + store.type());
System.out.println();
}
}
}
Gave me this output:
/ (/dev/sda5)
/dev/sda5
ext4
/* snip */
/media/TI103426W0D (/dev/sda2)
/dev/sda2
fuseblk
/media/flashdrive (/dev/sdb1)
/dev/sdb1
vfat
As it turns out, FileStore#type returns the format of the drive and FileStore#name returns the location of the device file for the drive. As far as I can tell, the only method which has the location of the drive is the toString method, but extracting the path name out of it seems dangerous because I'm not sure how well that particular solution would hold up on other operating systems and future versions of Java.
Is there something I'm missing here or is this simply not possible purely with Java?
System Information:
$ java -version
java version "1.7.0_03"
OpenJDK Runtime Environment (IcedTea7 2.1.1pre) (7~u3-2.1.1~pre1-1ubuntu2)
OpenJDK Client VM (build 22.0-b10, mixed mode, sharing)
$ uname -a
Linux jeffrey-pc 3.2.0-24-generic-pae #37-Ubuntu SMP Wed Apr 25 10:47:59 UTC 2012 i686 athlon i386 GNU/Linux
Here's a temporary work around until a better solution is found:
public Path getRootPath(FileStore fs) throws IOException {
Path media = Paths.get("/media");
if (media.isAbsolute() && Files.exists(media)) { // Linux
try (DirectoryStream<Path> stream = Files.newDirectoryStream(media)) {
for (Path p : stream) {
if (Files.getFileStore(p).equals(fs)) {
return p;
}
}
}
} else { // Windows
IOException ex = null;
for (Path p : FileSystems.getDefault().getRootDirectories()) {
try {
if (Files.getFileStore(p).equals(fs)) {
return p;
}
} catch (IOException e) {
ex = e;
}
}
if (ex != null) {
throw ex;
}
}
return null;
}
As far as I know, this solution will only work for Windows and Linux systems.
You have to catch the IOException in the Windows loop because if there is no CD in the CD drive an exception is thrown when you try to retrieve the FileStore for it. This might happen before you iterate over every root.
This is what I have ended up doing. This is limited to Windows + UNIX but avoids using external tools or additional library calls. It steals the information Java already has in the FileStore objects
LinuxFileStore definitely extends UnixFileStore, so it will work. Same deal for Solaris. Since Mac OS X is UNIX, it probably works there but I'm not sure because I couldn't see its subclass in any place I was looking.
public class FileStoreHacks {
/**
* Stores the known hacks.
*/
private static final Map<Class<? extends FileStore>, Hacks> hacksMap;
static {
ImmutableMap.Builder<Class<? extends FileStore>, Hacks> builder =
ImmutableMap.builder();
try {
Class<? extends FileStore> fileStoreClass =
Class.forName("sun.nio.fs.WindowsFileStore")
.asSubclass(FileStore.class);
builder.put(fileStoreClass, new WindowsFileStoreHacks(fileStoreClass));
} catch (ClassNotFoundException e) {
// Probably not running on Windows.
}
try {
Class<? extends FileStore> fileStoreClass =
Class.forName("sun.nio.fs.UnixFileStore")
.asSubclass(FileStore.class);
builder.put(fileStoreClass, new UnixFileStoreHacks(fileStoreClass));
} catch (ClassNotFoundException e) {
// Probably not running on UNIX.
}
hacksMap = builder.build();
}
private FileStoreHacks() {
}
/**
* Gets the path from a file store. For some reason, NIO2 only has a method
* to go in the other direction.
*
* #param store the file store.
* #return the path.
*/
public static Path getPath(FileStore store) {
Hacks hacks = hacksMap.get(store.getClass());
if (hacks == null) {
return null;
} else {
return hacks.getPath(store);
}
}
private static interface Hacks {
Path getPath(FileStore store);
}
private static class WindowsFileStoreHacks implements Hacks {
private final Field field;
public WindowsFileStoreHacks(Class<?> fileStoreClass) {
try {
field = fileStoreClass.getDeclaredField("root");
field.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalStateException("file field not found", e);
}
}
#Override
public Path getPath(FileStore store) {
try {
String root = (String) field.get(store);
return FileSystems.getDefault().getPath(root);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Denied access", e);
}
}
}
private static class UnixFileStoreHacks implements Hacks {
private final Field field;
private UnixFileStoreHacks(Class<?> fileStoreClass) {
try {
field = fileStoreClass.getDeclaredField("file");
field.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalStateException("file field not found", e);
}
}
#Override
public Path getPath(FileStore store) {
try {
return (Path) field.get(store);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Denied access", e);
}
}
}
}
I've not really explored this area of java, but I found this, which seems to be related. It uses File.listRoots()
There also seems to be a number of related questions linked there too.
This works for Windows:
public Path getFileStoreRootPath(FileStore fs) throws Exception {
for (Path root : FileSystems.getDefault().getRootDirectories()) {
if (Files.isDirectory(root) && Files.getFileStore(root).equals(fs)) {
return root;
}
}
throw new RuntimeException("Root directory for filestore " + fs + " not found");
}
Basically, by filtering by condition Files.isDirectory(root) we are excluding all CD/DVD drives which will throw IOException when compact-disc is not inserted.

Categories