I have created following simple program just to observe the object and memory information when I create list of String in java.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> strObj = new ArrayList<String>();
for (int i = 0; i < 1000; i++) {
strObj.add("abc");
}
}
}
But jProfiler shows me following information in Live Memory -> All Object view which I am not able to understand.
How so many char[] instance are created? I have created only 1000 String object, how around 9000 were created?
Kindly help me out interpreting this profiler information.
The dynamic memory views cannot answer this question. You have to go to the heap walker and select all char[] instances. Then look at the "Cumulated incoming references" view to analyze how the instances are referenced.
You can also switch on allocation recording at startup with an appropriate recording profile, then you can see where they were allocated.
Related
//object class
public class test
{
public test()
{
test t1 = new test();
}
}
//client class in same folder
public class Client
{
public static void main(String[] args)
{
test t = new test();
}
}
Does this just make infinite empty test objects?
What happens to the computer memory space/RAM do things just get deleted as more objects are continuously created?
Your initial reasoning is correct: you get an "infinite" number of test objects. Each object creates a new one. The constructor for the first object created (by main) never finishes.
However, the Java Virtual Machine (JVM) has a limit on the stack size. Every time the constructor calls the next constructor, an entry is pushed onto the stack. Within a short amount of time, you'll get a stack overflow exception and your program will be terminated.
I know Task has a method updateProgress, I would need to bind progressbar to task, however I cannot do that, as I do not have progressbar as an object.
My program has a TableView. Once user enters download url and clicks download new row created in the TableView. Row has some info and progressbar column. I then start a new thread - task. Where all download is being done and I need to update progress bar in that row somehow.
I tried binding SimpleDoubleProperty to the Task but it does not update progress bar...
James D solved this in Oracle JavaFX forum thread: Table cell progress indicator. I have just copied that solution into this answer.
The solution creates multiple tasks and monitors their progress via a set of progress bars in a TableView.
The original thread also includes a solution which uses ProgressIndicators in case you prefer those to ProgressBars.
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator ;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ProgressBarTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ProgressBarTableCellTest extends Application {
#Override
public void start(Stage primaryStage) {
TableView<TestTask> table = new TableView<TestTask>();
Random rng = new Random();
for (int i = 0; i < 20; i++) {
table.getItems().add(
new TestTask(rng.nextInt(3000) + 2000, rng.nextInt(30) + 20));
}
TableColumn<TestTask, String> statusCol = new TableColumn("Status");
statusCol.setCellValueFactory(new PropertyValueFactory<TestTask, String>(
"message"));
statusCol.setPrefWidth(75);
TableColumn<TestTask, Double> progressCol = new TableColumn("Progress");
progressCol.setCellValueFactory(new PropertyValueFactory<TestTask, Double>(
"progress"));
progressCol
.setCellFactory(ProgressBarTableCell.<TestTask> forTableColumn());
table.getColumns().addAll(statusCol, progressCol);
BorderPane root = new BorderPane();
root.setCenter(table);
primaryStage.setScene(new Scene(root));
primaryStage.show();
ExecutorService executor = Executors.newFixedThreadPool(table.getItems().size(), new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
for (TestTask task : table.getItems()) {
executor.execute(task);
}
}
public static void main(String[] args) {
launch(args);
}
static class TestTask extends Task<Void> {
private final int waitTime; // milliseconds
private final int pauseTime; // milliseconds
public static final int NUM_ITERATIONS = 100;
TestTask(int waitTime, int pauseTime) {
this.waitTime = waitTime;
this.pauseTime = pauseTime;
}
#Override
protected Void call() throws Exception {
this.updateProgress(ProgressIndicator.INDETERMINATE_PROGRESS, 1);
this.updateMessage("Waiting...");
Thread.sleep(waitTime);
this.updateMessage("Running...");
for (int i = 0; i < NUM_ITERATIONS; i++) {
updateProgress((1.0 * i) / NUM_ITERATIONS, 1);
Thread.sleep(pauseTime);
}
this.updateMessage("Done");
this.updateProgress(1, 1);
return null;
}
}
}
Explanatory Text Based on Comment Questions
You only need to read this section if you are having difficulties understanding how the above code works and want to gain a deeper understanding of cell value and property connections.
There is no kind of binding here (at least I do not see).
The binding (or ChangeListener, which amounts to the same thing) is hidden behind the implementation of the PropertyValueFactory and the ProgressBarTableCell. Let's look at the relevant code:
TableColumn<TestTask, Double> progressCol = new TableColumn("Progress");
progressCol.setCellValueFactory(
new PropertyValueFactory<TestTask, Double>("progress")
);
progressCol.setCellFactory(
ProgressBarTableCell.<TestTask> forTableColumn()
);
The progressCol is defined to take a TestTask as the data row and extract a double value out of the test task property.
The cell value factory defines how the double value for the column is populated. It is defined based upon a PropertyValueFactory which takes the parameter "progress". This tells the property value factory to use JavaFX naming conventions and the Java reflection API to lookup relevant methods to retrieve the data from a TestTask instance. In this case it will invoke a method named progressProperty() on the TestTask instance to retrieve the ReadOnlyDoubleProperty reflecting the tasks progress.
As it states in it's documentation, the PropertyValueFactory is just short hand for the mess of code below, but the key fact is that it is returning an ObservableValue which the Table implementation can use to set the value of the cell as the cell changes.
TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name");
firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
// p.getValue() returns the Person instance for a particular TableView row
return p.getValue().firstNameProperty();
}
});
OK, so now we have a cell's value being reflected to the double value of the task's progress whenever the task makes any progress. But we still need to graphically represent that double value somehow. This is what the ProgressBarTableCell does. It is a table cell which contains a progress bar. The forTableColumn method creates a factory which produces the ProgressBarTableCells for each non-empty row in the column and sets the progress bar's progress to match the cell value which has been linked to the task's progress property by the PropertyValueFactory.
Confusing in understanding the detailed implementation . . . sure. But these high level helper factories and cells take care of a lot of the low level linkage details for you so that you don't need to code them over and over and from a plain API usage point of view it is (hopefully) simple and logical.
Also there is no properties (like SimpleStringProperty etc.) so the question would be, what if I need like two more columns with SimpleStringProperty, how do I add them to this kind of TableView?
Use the PropertyValueFactory once again. Let's image you have a string property called URL, then you can add the columns like this:
TableColumn<TestTask, Double> urlCol = new TableColumn("URL");
urlCol.setCellValueFactory(
new PropertyValueFactory<TestTask, Double>("url")
);
Note we only needed to set the cell value factory, this is because the default cell factory for the column will return a cell containing a label which directly displays the string value of the cell.
Now for the above to work correctly we need a method on TestTask which provides a url for the task, for example:
final ReadOnlyStringWrapper url = new ReadOnlyStringWrapper();
public TestTask(String url) {
this.url.set(url);
}
public ReadOnlyStringProperty urlProperty() {
return url.getReadOnlyProperty()
}
Note that the naming convention is really important here, it must be urlProperty() it can't be anything else or the PropertyValueFactory won't find the property value accessor.
Note for these purposes, a simple String value with a getUrl() would have worked just as well as a property as a PropertyValueFactory will work with a getter as well as a property method. The only advantage of using a property method is that it allows the table value data to update automatically based on property change events, which is not possible with a straight getter. But here because the url is effectively final and doesn't change for a given task, it doesn't make a difference whether a getter or property method is provided for this file from the task.
on trying to monitor object sizes, string objects are not shown in the profiled results.
Can anyone tell me wat is the procedure to make them shown in results....
public class calling extends called {
called myobj3 = new called();
called myobj4 = new called();
public void function() {
myobj3.d="Plz";
myobj3.e="Help";
myobj4.d="Thank";
myobj4.e="You";
myobj3.act();
myobj4.act();
}
public static void main(String [] args) {
System.out.println("calls an object from called.java");
calling obj = new calling();
obj.function();
}
}
class called {
public String d;
public String e;
public void act() {
System.out.println(d+e);
}
}
memory profile Retained size Shallow Size
[Unreachable] called 40 40
[Unreachable] called 40 40
Perhaps, your objects have been collected or scheduled for collection (unreachable). In which point do you capture memory snapshot?
Disclaimer: I'm a YourKit developer.
In an attempt to solve this problem, I built a (very) small project that is reproducing part of it. It is a NetBeans project using Glassfish v2.1.1 and OpenJpa-1.2.2.
Globally, the goal is to be able to reload dynamically some business code (called 'tasks') without the need to (re)make a full deployment (eg via asadmin). In the project there are two of them: PersonTask and AddressTask which are simply accessing some data and printing them out.
In order to do that, I've implemented a custom class loader that read the binary of class files and inject it via the defineClass method. Basically, this CustomClassLoader is a singleton and is implemented like this:
public class CustomClassLoader extends ClassLoader {
private static CustomClassLoader instance;
private static int staticId = 0;
private int id; //for debugging in VisualVM
private long threadId; //for debugging in VisualVM
private CustomClassLoader(ClassLoader parent) {
super(parent);
threadId = Thread.currentThread().getId();
id = staticId;
++staticId;
}
private static CustomClassLoader getNewInstance() {
if (instance!=null) {
CustomClassLoader ccl = instance;
instance = null;
PCRegistry.deRegister(ccl); //https://issues.apache.org/jira/browse/GERONIMO-3326
ResourceBundle.clearCache(ccl); //found some references in there while using Eclipse Memory Analyzer Tool
Introspector.flushCaches(); //http://java.jiderhamn.se/category/classloader-leaks/
System.runFinalization();
System.gc();
}
ClassLoader parent = Thread.currentThread().getContextClassLoader();
instance = new CustomClassLoader(parent);
return instance;
}
//...
}
//this class is included in the EAR like a normal class
public abstract class AbstractTask {
protected Database database; /* wrapper around the EntityManager, filled when instance is created */
public abstract void process(Integer id);
}
//this one is dynamically loaded by the CustomClassLoader
public class PersonTask extends AbstractTask {
#Override
public void process(Integer id) {
//keep it empty for now
}
}
In my EJB facade (EntryPointBean), I simply do a lookup of the class, create a new instance of it and call the process method on it. The code in the project is slightly different, but the idea is quite the same:
CustomClassLoader loader = CustomClassLoader.getNewInstance();
Class<?> clazz = loader.loadClass("ch.leak.tasks.PersonTask");
Object instance = clazz.newInstance();
AbstractTask task = (AbstractTask)instance;
/* inject a new Database instance into the task */
task.process(...);
Until now, all is fine. If this code is run many times (via ch.leak.test.Test), there will be only one single instance of the CustomClassLoader when a heap analysis is done, meaning the previous instances have been successfully collected.
Now, here is the line triggering a leak:
public class PersonTask extends AbstractTask {
#Override
public void process(Integer id) {
Person p = database.getEntity("SELECT p FROM Person p WHERE p.personpk.idpk=?1", new Long(id));
//...
}
}
This simple access to the database has a strange consequence: the first time the code is run, the CustomClassLoader being used will never be garbage collected (even without any GC roots). However, all the further CustomClassLoader created won't leak.
As we can see in the dump below (done with VisualVM), the CustomClassLoader with instance id 0 is never garbage collected...
Finally, one other thing I've seen when exploring the heap dump: my entities are declared twice in the PermGen and half of them have no instances and also no GC root (but they are not linked to the CustomClassLoader).
It seems that OpenJPA has something to do with those leaks... but I don't know where I can search for more information of what I'm doing wrong. I have also put the heap dump directly in the zip with the project.
Does anyone have an idea ?
Thanks !
I have an example piece of code the illustrates issues in my code when GC.Collect is carried out on a class having a ReaderWriterLockSlim member variable. The GC.Collect takes between 2 and 3 seconds to run. I need to carry out GC at regular intervals because my applicaton is extremely memory intensive.
namespace WpfApplication12
{
public class DataItem
{
private readonly ReaderWriterLockSlim m_propertyLock = new ReaderWriterLockSlim();
public DataItem()
{
}
}
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
List<DataItem> dataItemList = new List<DataItem>();
for (int i = 0; i < 100000; i++)
{
dataItemList.Add(new DataItem());
}
Debug.WriteLine(DateTime.Now.ToString());
GC.Collect();
Debug.WriteLine(DateTime.Now.ToString());
}
}
}
Has anyone had similar problems?
Thanks
Ian
I'd ask if you really need a ReaderWriterLockSlim for each of your DataItem classes?
Seems like bad design to me to have that many handles floating about. After-all, that's what will be causing the delay...
The memory issue may be caused if the readerwriterlockslim is called from multiple threads. I believe it will store some information of the threads which can cause the memory consumption to bloat. I would recommend trying to figure out a solution where you can bring down the number of thread that are calling the readerwriterlockslim.