Skip to content

Commit de72e9c

Browse files
committed
[JAVA-279]: ObjectId could generate duplicate ids if used in different classloader
1 parent b1a588d commit de72e9c

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

src/main/com/mongodb/DBCollection.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public WriteResult remove( DBObject o )
203203
* @param ref query used to search
204204
* @param fields the fields of matching objects to return
205205
* @param numToSkip will not return the first <tt>numToSkip</tt> matches
206-
* @param batchSize if positive, is the # of objects per batch sent back from the db. all objects that match will be returned. if batchSize < 0, its a hard limit, and only 1 batch will either batchSize or the # that fit in a batch
206+
* @param batchSize if positive, represents the size of each batch of objects retrieved. If negative, it limits the total number of objects retrieved.
207207
* @param options - see Bytes QUERYOPTION_*
208208
* @return the objects, if found
209209
* @dochub find
@@ -212,10 +212,11 @@ public WriteResult remove( DBObject o )
212212

213213
/**
214214
* Finds an object.
215+
* Calls {@link DBCollection#find(com.mongodb.DBObject, com.mongodb.DBObject, int, int)} and applies the query options
215216
* @param ref query used to search
216217
* @param fields the fields of matching objects to return
217218
* @param numToSkip will not return the first <tt>numToSkip</tt> matches
218-
* @param batchSize if positive, is the # of objects per batch sent back from the db. all objects that match will be returned. if batchSize < 0, its a hard limit, and only 1 batch will either batchSize or the # that fit in a batch
219+
* @param batchSize if positive, represents the size of each batch of objects retrieved. If negative, it limits the total number of objects retrieved.
219220
* @param options - see Bytes QUERYOPTION_*
220221
* @return the objects, if found
221222
* @throws MongoException
@@ -231,7 +232,7 @@ public final DBCursor find( DBObject ref , DBObject fields , int numToSkip , int
231232
* @param ref query used to search
232233
* @param fields the fields of matching objects to return
233234
* @param numToSkip will not return the first <tt>numToSkip</tt> matches
234-
* @param batchSize if positive, is the # of objects per batch sent back from the db. all objects that match will be returned. if batchSize < 0, its a hard limit, and only 1 batch will either batchSize or the # that fit in a batch
235+
* @param batchSize if positive, represents the size of each batch of objects retrieved. If negative, it limits the total number of objects retrieved.
235236
* @return the objects, if found
236237
* @dochub find
237238
*/

src/main/com/mongodb/DBCursor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ public String toString() {
655655
sb.append(", fields=").append(getKeysWanted());
656656
sb.append(", numIterated=").append(_num);
657657
if (_numWanted > 0)
658-
sb.append(", numWanted=").append(_numWanted);
658+
sb.append(", limit=").append(_numWanted);
659659
if (_skip > 0)
660660
sb.append(", skip=").append(_skip);
661661
return sb.toString();

src/main/org/bson/types/ObjectId.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ private static int _curtime(){
342342
static {
343343

344344
try {
345-
345+
// build a 2-byte machine piece based on NICs info
346346
final int machinePiece;
347347
{
348348
StringBuilder sb = new StringBuilder();
@@ -354,17 +354,25 @@ private static int _curtime(){
354354
machinePiece = sb.toString().hashCode() << 16;
355355
LOGGER.fine( "machine piece post: " + Integer.toHexString( machinePiece ) );
356356
}
357-
357+
358+
// add a 2 byte process piece. It must represent not only the JVM but the class loader.
359+
// Since static var belong to class loader there could be collisions otherwise
358360
final int processPiece;
359361
{
360-
int temp = new java.util.Random().nextInt();
362+
int processId = new java.util.Random().nextInt();
361363
try {
362-
temp = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();
364+
processId = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();
363365
}
364366
catch ( Throwable t ){
365367
}
366-
temp = temp & 0xFFFF;
367-
processPiece = temp;
368+
369+
ClassLoader loader = ObjectId.class.getClassLoader();
370+
int loaderId = loader != null ? System.identityHashCode(loader) : 0;
371+
372+
StringBuilder sb = new StringBuilder();
373+
sb.append(Integer.toHexString(processId));
374+
sb.append(Integer.toHexString(loaderId));
375+
processPiece = sb.toString().hashCode() & 0xFFFF;
368376
LOGGER.fine( "process piece: " + Integer.toHexString( processPiece ) );
369377
}
370378

0 commit comments

Comments
 (0)