The server uses a cookie (similar to the HTTP session cookie mechanism) to maintain the state of the search requests in order to track the results being sent to the client. The paged results control is specified in RFC 2696. The classes below provide the functionality required to support paged results control.
    // Activate paged results
     int pageSize = 5; // 5 entries per page
     byte[] cookie = null;
     int total;
     ctx.setRequestControls(new Control[]{ 
         new PagedResultsControl(pageSize, Control.CRITICAL) });
     // Perform the search
     NamingEnumeration results =
         ctx.search("", "(objectclass=*)", new SearchControls());
   // Iterate over a batch of search results sent by the server
         while (results != null && results.hasMore()) {
             // Display an entry
             SearchResult entry = (SearchResult)results.next();
             System.out.println(entry.getName());
             // Handle the entry's response controls (if any)
             if (entry instanceof HasControls) {
                 // ((HasControls)entry).getControls();
             }
         }
   // Examine the paged results control response 
         Control[] controls = ctx.getResponseControls();
         if (controls != null) {
             for (int i = 0; i < controls.length; i++) {
                 if (controls[i] instanceof PagedResultsResponseControl) {
                     PagedResultsResponseControl prrc =
                         (PagedResultsResponseControl)controls[i];
                     total = prrc.getResultSize();
                     cookie = prrc.getCookie();
                 } else {
                     // Handle other response controls (if any)
                 }
             }
         }   
  // Re-activate paged results
         ctx.setRequestControls(new Control[]{
             new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
The complete JNDI example can be found here.