[ 
https://issues.apache.org/jira/browse/HTTPCORE-513?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Ion Moldovan updated HTTPCORE-513:
----------------------------------
    Description: 
Steps:
 # create a PHP page with the following content: 
 ## <?php
 $response='abc';
 echo str_pad($response, 2147483647);
 # send a request using jMeter to the said page

Expected result: the request is received

Actual result: the VM fails with:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
 Dumping heap to java_pid20344.hprof ...
 Heap dump file created [3275879706 bytes in 7.490 secs]
 Uncaught Exception java.lang.OutOfMemoryError: Requested array size exceeds VM 
limit. See log file for details.

 

Proposed solution:
 * rewrite org.apache.http.nio.util.ExpandableBuffer.expand() to:

 
{code:java}
/**
* Expands buffer's capacity.
*/
protected void expand() {
  int newcapacity = (this.buffer.capacity() + 1) << 1;
  if (newcapacity < 0) {
    int headRoom = Integer.max(Long.BYTES, 8);
    // Reason: In GC the size of objects is passed as int (2 bytes). 
    // Then, the header size of the objects is added to the size. 
    // Long has the longest header available. Object header seems to be linked 
to it. 
    // Details: I added a minimum of 8 just to be safe and because 8 is used in 
    // java.lang.Object.ArrayList: private static final int MAX_ARRAY_SIZE = 
2147483639.

    newcapacity = Integer.MAX_VALUE - headRoom; 
  } 
  expandCapacity(newcapacity); 
}{code}
 

  was:
Steps:
 # create a PHP page with the following content: 
 ## <?php
 $response='abc';
 echo str_pad($response, 2147483647);
 # send a request using jMeter to the said page

Expected result: the request is received

Actual result: the VM fails with:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
 Dumping heap to java_pid20344.hprof ...
 Heap dump file created [3275879706 bytes in 7.490 secs]
 Uncaught Exception java.lang.OutOfMemoryError: Requested array size exceeds VM 
limit. See log file for details.

 

Proposed solution:
 * rewrite org.apache.http.nio.util.ExpandableBuffer.expand() to:

 
{code:java}
/**
* Expands buffer's capacity.
*/
protected void expand() {
  int newcapacity = (this.buffer.capacity() + 1) << 1;
  if (newcapacity < 0) {
    int headRoom = Integer.max(Long.BYTES, 8);
    // Reason: In GC the size of objects is passed as int (32 bits). 
    // Then, the header size of the objects is added to the size. 
    // Long has the longest header available. Object header seems to be linked 
to it. 
    // Details: I added a minimum of 8 just to be safe and because 8 is used in 
    // java.lang.Object.ArrayList: private static final int MAX_ARRAY_SIZE = 
2147483639.

    newcapacity = Integer.MAX_VALUE - headRoom; 
  } 
  expandCapacity(newcapacity); 
}{code}
 


> ExpandableBuffer breaks on large response
> -----------------------------------------
>
>                 Key: HTTPCORE-513
>                 URL: https://issues.apache.org/jira/browse/HTTPCORE-513
>             Project: HttpComponents HttpCore
>          Issue Type: Bug
>          Components: HttpCore, HttpCore NIO
>    Affects Versions: 4.4.9
>            Reporter: Ion Moldovan
>            Priority: Critical
>
> Steps:
>  # create a PHP page with the following content: 
>  ## <?php
>  $response='abc';
>  echo str_pad($response, 2147483647);
>  # send a request using jMeter to the said page
> Expected result: the request is received
> Actual result: the VM fails with:
> java.lang.OutOfMemoryError: Requested array size exceeds VM limit
>  Dumping heap to java_pid20344.hprof ...
>  Heap dump file created [3275879706 bytes in 7.490 secs]
>  Uncaught Exception java.lang.OutOfMemoryError: Requested array size exceeds 
> VM limit. See log file for details.
>  
> Proposed solution:
>  * rewrite org.apache.http.nio.util.ExpandableBuffer.expand() to:
>  
> {code:java}
> /**
> * Expands buffer's capacity.
> */
> protected void expand() {
>   int newcapacity = (this.buffer.capacity() + 1) << 1;
>   if (newcapacity < 0) {
>     int headRoom = Integer.max(Long.BYTES, 8);
>     // Reason: In GC the size of objects is passed as int (2 bytes). 
>     // Then, the header size of the objects is added to the size. 
>     // Long has the longest header available. Object header seems to be 
> linked to it. 
>     // Details: I added a minimum of 8 just to be safe and because 8 is used 
> in 
>     // java.lang.Object.ArrayList: private static final int MAX_ARRAY_SIZE = 
> 2147483639.
>     newcapacity = Integer.MAX_VALUE - headRoom; 
>   } 
>   expandCapacity(newcapacity); 
> }{code}
>  



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@hc.apache.org
For additional commands, e-mail: dev-h...@hc.apache.org

Reply via email to