merged R-1_9 release tag against the root-B-1_9
This commit is contained in:
18
unittest/com/jacob/com/JacobObjectTest.java
Normal file
18
unittest/com/jacob/com/JacobObjectTest.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.jacob.com;
|
||||
|
||||
/**
|
||||
* @author joe
|
||||
*
|
||||
* This will eventually be changed to a unit test.
|
||||
*
|
||||
* Run in Eclipse with command line arguments
|
||||
* -Djava.library.path=d:/jacob/release -Dcom.jacob.autogc=false
|
||||
*/
|
||||
public class JacobObjectTest {
|
||||
|
||||
public static void main(String args[]) throws Exception
|
||||
{
|
||||
System.out.println("build version is "+JacobObject.getBuildVersion());
|
||||
System.out.println("build date is "+JacobObject.getBuildDate());
|
||||
}
|
||||
}
|
||||
122
unittest/com/jacob/com/ROT2Test.java
Normal file
122
unittest/com/jacob/com/ROT2Test.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package com.jacob.com;
|
||||
|
||||
/**
|
||||
* This test class exists to test the WeakRefernce implementation .
|
||||
*
|
||||
* It is not useful if there isn't one at this time
|
||||
*
|
||||
* This will eventually be changed to a unit test.
|
||||
*
|
||||
* Run in Eclipse with command line arguments
|
||||
* -Djava.library.path=d:/jacob/release -Dcom.jacob.autogc=false
|
||||
*/
|
||||
public class ROT2Test
|
||||
{
|
||||
|
||||
public static void main(String args[]) throws Exception
|
||||
{
|
||||
ROT2TestThread threads[] = new ROT2TestThread[4];
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
threads[i] = new ROT2TestThread("thread-" + i, 3000);
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
threads[i].start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This wil try and exercise the thread support in the ROT
|
||||
**/
|
||||
|
||||
class ROT2TestThread extends Thread
|
||||
{
|
||||
private java.util.List ThreadObjects;
|
||||
|
||||
private boolean DivideMode = true;
|
||||
|
||||
private int initialRunSize = 0;
|
||||
/**
|
||||
* @param arg0
|
||||
*/
|
||||
public ROT2TestThread(String arg0, int iStartCount)
|
||||
{
|
||||
super(arg0);
|
||||
initialRunSize = iStartCount;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A semi-complexe serie of steps to put the ROT under stress. 1) discard
|
||||
* half the objects we've created 2) if size is greater than 1 but not a
|
||||
* even number, add 1 new object 3) stop when size is 1.
|
||||
*
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
// something that keeps object references around
|
||||
// so the gc can't collect them
|
||||
// we need to create these in the thread so they end up in the right ROT table
|
||||
ThreadObjects = new java.util.ArrayList(initialRunSize);
|
||||
for (int i = 0; i < initialRunSize; i++)
|
||||
{
|
||||
// create the object
|
||||
Variant aNewVariant = new Variant(getName() + "_" + i);
|
||||
// create a hard reference to it
|
||||
ThreadObjects.add(aNewVariant);
|
||||
}
|
||||
|
||||
while (ThreadObjects.size() > 1)
|
||||
{
|
||||
String message = "";
|
||||
message = getName()+" Workingset=" +ThreadObjects.size()
|
||||
+" ROT: ";
|
||||
message += "(before additions and gc "+ROT.getThreadObjects(false).size()+")";
|
||||
// if there is an odd number of objects greater than 2
|
||||
if (ThreadObjects.size() > 2 && ThreadObjects.size() % 2 != 0)
|
||||
{
|
||||
// add a new object
|
||||
Variant aNewVariant = new Variant(getName() + "_*" + ThreadObjects.size());
|
||||
ThreadObjects.add(aNewVariant);
|
||||
}
|
||||
// now iterate across all the objects in our list
|
||||
for (int i = ThreadObjects.size(); i > 0; i--)
|
||||
{
|
||||
// removing every other one?
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
// remove the reference so gc can get it
|
||||
ThreadObjects.remove(i-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
// simulate the system under load and run the GC
|
||||
// should end up with weak references with no objects attached
|
||||
Thread.sleep(9);
|
||||
} catch (InterruptedException e){
|
||||
// the VM doesn't want us to sleep anymore,
|
||||
// so get back to work
|
||||
}
|
||||
message += " (before gc, after additions "+ROT.getThreadObjects(false).size()+")";
|
||||
System.gc();
|
||||
message += " (after System.gc "+ROT.getThreadObjects(false).size()+")";
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Another test would be to overide this to always return the same name.
|
||||
* That would really screw the ROT!
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
131
unittest/com/jacob/com/ROT3Test.java
Normal file
131
unittest/com/jacob/com/ROT3Test.java
Normal file
@@ -0,0 +1,131 @@
|
||||
package com.jacob.com;
|
||||
|
||||
/**
|
||||
* This trys to exercise ROT's garbage collecion
|
||||
* This is named this way because the build.xml
|
||||
* ignores files ending in Test when building the binary zip file
|
||||
*
|
||||
* This will eventually be changed to a unit test.
|
||||
*
|
||||
* Run in Eclipse with command line arguments
|
||||
* -Djava.library.path=d:/jacob/release -Dcom.jacob.autogc=false
|
||||
*/
|
||||
public class ROT3Test
|
||||
{
|
||||
|
||||
public static void main(String args[]) throws Exception
|
||||
{
|
||||
ROT3TestThread threads[] = new ROT3TestThread[4];
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
threads[i] = new ROT3TestThread("thread-" + i, 3000+i*10);
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
threads[i].start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This wil try and exercise the thread support in the ROT
|
||||
**/
|
||||
|
||||
class ROT3TestThread extends Thread
|
||||
{
|
||||
private java.util.List ThreadObjects;
|
||||
|
||||
private boolean DivideMode = true;
|
||||
|
||||
private int initialRunSize = 0;
|
||||
/**
|
||||
* @param arg0
|
||||
*/
|
||||
public ROT3TestThread(String arg0, int iStartCount)
|
||||
{
|
||||
super(arg0);
|
||||
initialRunSize = iStartCount;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A semi-complexe serie of steps to put the ROT under stress. 1) discard
|
||||
* half the objects we've created 2) if size is greater than 1 but not a
|
||||
* even number, add 1 new object 3) stop when size is 1.
|
||||
*
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
// something that keeps object references around
|
||||
// so the gc can't collect them
|
||||
// we need to create these in the thread so they end up in the right ROT table
|
||||
ThreadObjects = new java.util.ArrayList(initialRunSize);
|
||||
for (int i = 0; i < initialRunSize; i++)
|
||||
{
|
||||
// create the object
|
||||
Variant aNewVariant = new Variant(getName() + "_" + i);
|
||||
// create a hard reference to it
|
||||
ThreadObjects.add(aNewVariant);
|
||||
}
|
||||
|
||||
while (ThreadObjects.size() > 1)
|
||||
{
|
||||
String message = "";
|
||||
message = getName()+" Workingset=" +ThreadObjects.size()
|
||||
+" ROT: "+ROT.getThreadObjects(true).hashCode();
|
||||
message += "before mods and gc "+ROT.getThreadObjects(true).size()+")";
|
||||
// if there is an odd number of objects greater than 2
|
||||
if (ThreadObjects.size() > 10)
|
||||
{
|
||||
message+= " ++ ";
|
||||
for ( int i = 0 ; i < ThreadObjects.size()/4 ; i++){
|
||||
// add a new object
|
||||
Variant aNewVariant = new Variant(getName() + "_*" + ThreadObjects.size());
|
||||
ThreadObjects.add(aNewVariant);
|
||||
}
|
||||
}
|
||||
// now iterate across all the objects in our list
|
||||
message += " -- ";
|
||||
for (int i = ThreadObjects.size(); i > 0; i--)
|
||||
{
|
||||
// removing every other one?
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
// remove the reference so gc can get it
|
||||
if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION){
|
||||
ROT.removeObject((JacobObject)ThreadObjects.get(i-1));
|
||||
}
|
||||
ThreadObjects.remove(i-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
message += " (after mods "+ROT.getThreadObjects(true).size()+")";
|
||||
// comm
|
||||
if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION){
|
||||
ROT.clearObjects();
|
||||
}
|
||||
System.gc();
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException ie){
|
||||
|
||||
}
|
||||
message += " (after gc "+ROT.getThreadObjects(true).size()+")";
|
||||
message += " Should see GC if debug turned on...";
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Another test would be to overide this to always return the same name.
|
||||
* That would really screw the ROT!
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
73
unittest/com/jacob/com/ROTTest.java
Normal file
73
unittest/com/jacob/com/ROTTest.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package com.jacob.com;
|
||||
import com.jacob.com.ROT;
|
||||
/**
|
||||
* This trys to exercise ROT's garbage collecion
|
||||
*
|
||||
* This will eventually be changed to a unit test.
|
||||
*
|
||||
* Run in Eclipse with command line arguments
|
||||
* -Djava.library.path=d:/jacob/release -Dcom.jacob.autogc=false
|
||||
*/
|
||||
public class ROTTest {
|
||||
|
||||
public static void main(String args[]) throws Exception
|
||||
{
|
||||
int sizeAfterBuild = 0;
|
||||
int sizeBeforeGC = 0;
|
||||
int sizeAfterGC = 0;
|
||||
|
||||
debug("creating 10,000 object sets");
|
||||
for ( int i = 0 ; i <= 10000; i++){
|
||||
SafeArray a1 = new SafeArray(Variant.VariantVariant, 2);
|
||||
a1.setVariant(0, new Variant("foo"));
|
||||
a1.setVariant(1, new Variant("bar"));
|
||||
}
|
||||
sizeAfterBuild = ROT.getThreadObjects(false).size();
|
||||
if (sizeAfterBuild < 10000){
|
||||
debug("Something got GC'd: "+sizeAfterBuild);
|
||||
} else if (sizeAfterBuild > 10000){
|
||||
debug("More than expected: "+sizeAfterBuild);
|
||||
} else {
|
||||
debug("They're all there");
|
||||
}
|
||||
// add more to the VM
|
||||
debug("Flooding Memory to force GC");
|
||||
for ( int i = 0 ; i <= 10000; i++){
|
||||
new String("this is just some text to see if we can force gc "+i);
|
||||
}
|
||||
// storage will hold weak references until the next JacobObject is created
|
||||
System.gc();
|
||||
sizeBeforeGC = ROT.getThreadObjects(false).size();
|
||||
debug("Objects left after flood and gc but before adding a new object that clean's up weak references: "+sizeBeforeGC);
|
||||
debug("Creating single object. This adds one and causes ROT to clean up GC'd");
|
||||
new JacobObject();
|
||||
sizeAfterGC = ROT.getThreadObjects(false).size();
|
||||
debug("Objects left after adding one (caused weak ref objects to be removed): "+sizeAfterGC);
|
||||
new JacobObject();
|
||||
if (ROT.getThreadObjects(false).size() != sizeAfterGC+1){
|
||||
debug("Unexpected number of objects after adding only one more "+ROT.getThreadObjects(false).size());
|
||||
} else {
|
||||
debug("Found number expected after adding one more " +(sizeAfterGC+1) );
|
||||
}
|
||||
ROT.clearObjects();
|
||||
if (ROT.getThreadObjects(false) == null){
|
||||
debug("ROT pool was destroyed as expected after clearObjects called.");
|
||||
} else {
|
||||
debug("ROT pool for thread still exists when it shouldn't");
|
||||
}
|
||||
|
||||
//========= part two ================================
|
||||
debug("Verifying doesn't blow up with double release");
|
||||
for ( int i = 0 ; i <= 10000; i++){
|
||||
new JacobObject();
|
||||
}
|
||||
// force safeRelease call on all objects
|
||||
ROT.clearObjects();
|
||||
// now force the gc to go collect them, running safeRelease again
|
||||
System.gc();
|
||||
}
|
||||
|
||||
private static void debug(String message){
|
||||
System.out.println(Thread.currentThread().getName()+" "+message);
|
||||
}
|
||||
}
|
||||
105
unittest/com/jacob/com/SafeArrayReleaseTest.java
Normal file
105
unittest/com/jacob/com/SafeArrayReleaseTest.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package com.jacob.com;
|
||||
|
||||
/**
|
||||
* SF 1085370
|
||||
In my understatnding, an instance of SafeArray java
|
||||
class has a
|
||||
value of a pointer to VARIANT structure that contains a
|
||||
pointer to
|
||||
a SAFEARRAY strucuture.
|
||||
|
||||
On the other hand, we can create a Variant object from
|
||||
the
|
||||
SafeArray object like this:
|
||||
SafeArray sa = ...;
|
||||
Variant val = new Variant(sa);
|
||||
the val object has a pointer to another VARIANT
|
||||
structure that
|
||||
contains a pointer to the same SAFEARRAY structure.
|
||||
|
||||
In this case, the val object has a pointer to another
|
||||
VARIANT that
|
||||
contains a pointer to the same SAFEARRAY like this:
|
||||
|
||||
+-----------+
|
||||
|SafeArray | +------------+
|
||||
| m_pV--->VARIANT(a) |
|
||||
+-----------+ | VT_ARRAY| +---------+
|
||||
| parray---->SAFEARRAY|
|
||||
+------------+ +^--------+
|
||||
|
|
||||
+-----------+ |
|
||||
|Variant | +------------+ |
|
||||
| m_pVariant--->VARIANT(b) | |
|
||||
+-----------+ | VT_ARRAY| |
|
||||
| parray-----+
|
||||
+------------+
|
||||
|
||||
When previous objects are rereased by
|
||||
ComThread.Release(),
|
||||
first the VARIANT(a) is released by VariantClear()
|
||||
function,
|
||||
and second the VARIANT(b) is released by VariantClear()
|
||||
function too.
|
||||
But the SAFEARRAY was already released by the
|
||||
VARIANT(a).
|
||||
|
||||
So, in my enviroment (WinXP + J2SDK 1.4.1) the
|
||||
following java program
|
||||
is sometimes crash with EXCEPTION_ACCESS_VIOLATION.
|
||||
|
||||
|
||||
To solve this problem, it is nessesary to copy the
|
||||
SAFEARRAY like this:
|
||||
|
||||
+-----------+
|
||||
|Variant | +------------+
|
||||
| m_pVariant--->VARIANT(a) |
|
||||
+-----------+ | VT_ARRAY| +---------+
|
||||
| parray---->SAFEARRAY|
|
||||
+------------+ +|--------+
|
||||
|
|
||||
+-----------+ | copySA()
|
||||
|SafeArray | +------------+ |
|
||||
| m_pV--->VARIANT(b) | V
|
||||
+-----------+ | VT_ARRAY| +---------+
|
||||
| parray---->SAFEARRAY|
|
||||
+------------+ +---------+
|
||||
*/
|
||||
|
||||
public class SafeArrayReleaseTest
|
||||
{
|
||||
final static int MAX = 300;
|
||||
public static void main(String[] args)
|
||||
{
|
||||
int count;
|
||||
System.out.println("Starting test for max = "+MAX);
|
||||
for(count = 1; count<MAX; count++)
|
||||
{
|
||||
int i = 0;
|
||||
try
|
||||
{
|
||||
ComThread.InitMTA();
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
SafeArray a1 = new SafeArray(Variant.VariantVariant, 2);
|
||||
a1.setVariant(0, new Variant("foo"));
|
||||
a1.setVariant(1, new Variant("bar"));
|
||||
Variant v = new Variant(a1);
|
||||
SafeArray a2 = v.toSafeArray(true);
|
||||
}
|
||||
ComThread.Release();
|
||||
System.gc();
|
||||
//System.out.print(".");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("\nTest fails with i = " + i + " (max = "+MAX+")");
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
System.out.println("\nTest ends with count = " + count + " (max = "+MAX+")");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user