Arraysクラスをimportせずに自身でソートアルゴリズムを実装する課題です。
配列の要素数によっておこなうソートの方法を変更したいのです。
(a)要素数1-6:基準値不要のインサーションソート ←実装OK
(b)要素数7:クイックソート(基準値:配列の真ん中の値) ←実装OK
(c)要素数8-40:クイックソート(基準値:配列の先頭,真ん中,末尾の値の中から2番目
に大きい値) ←今ここ!悩んでいる!
(d)要素数41-:クイックソート(基準値:配列を8等分した位置にある9つの値を選び,4~6番目に大きい値のどれか) ←まだ手つけていない

今エラーが出て、うまくいかなくて悩んでいるところが(c)です。
この(c)が配列の値が1の位のみ({3,5,2,6,8,9,4,1}みたいなやつ)のときはソートが完了するのですが、それ以外の配列だとエラーが出ます。
ちなみにエラーがでるのは2週目(再帰1週目)で、insertionSort(b);とquickSort2(a, i, toIndex);の部分です。
1週目はうまくいくのです。しかし配列を2グループわけた2週目(再帰1週目)からなにかがうまくいってないのだと思います。

エラー内容:無限ループに陥っています
試しに quickSort2(a, fromIndex, j);の後ろに
System.out.println(j);をつけてみると
2
2
2
2
2
2
.... という無限ループが起こりました。
Exception in thread "main" java.lang.StackOverflowError
at lesson02.ArraySort.quickSort2(ArraySort.java:72)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
at lesson02.ArraySort.quickSort2(ArraySort.java:85)
.....

package lesson02;
import java.util.Arrays;

public class ArraySort {

    //要素数で割った値(=gap)を左端から順にたしていく
    //2晩目に大きい値の添え字を戻すようにする

    public void sort(int[] a){

        int leaf = leafValue(a); //要素数の範囲を決める値
        switch(leaf){


        case 1:
            System.out.println("(a)インサーションソートを行います.");
            insertionSort(a);
            break;

        case 2:
            System.out.println("(b)でクイックソートを行います.");
            quickSort1(a,0, a.length - 1);
            break;

        case 3:
            System.out.println("(c)でクイックソートを行います.");
            quickSort2(a,0, a.length - 1);
            break;

        case 4:
            System.out.println("(d)でクイックソートを行います.");
            quickSort3(a,0, a.length - 1);
            break;

        default: System.out.println("やり直してください.");
        }
    }

    public static void insertionSort(int[] a){
        for(int i=1;i<a.length;i++){
            int j;
            int tmp = a[i];
            for(j=i;j>0 && a[j-1]>tmp;j--){
                a[j] = a[j-1];
            }
            a[j] = tmp;
        }
    }

    public static void quickSort1(int[] a, int fromIndex, int toIndex){
        int x = a[(fromIndex + toIndex) / 2]; // 基準値
        int i = fromIndex; // 基準値より大きい値を探すカーソル
        int j = toIndex; // 基準値より小さい値を探すカーソル

        while (i <= j) { // カーソルの位置関係が逆転しない限りループする
            while (a[i] < x)
                i++;
            while (a[j] > x)
                j--;
            if (i <= j)
                swap(a, i++, j--);
        }
        if (fromIndex < j)
            quickSort1(a, fromIndex, j); // 左側の再帰的なソート
        if (i < toIndex)
            quickSort1(a, i, toIndex); // 右側の再帰的なソート
    }   

    //うまくいかない、悩んでいるところ!!!!!!
    //配列の先頭,真ん中,末尾の値の中から2番目に大きい値を基準値にする
    public static void quickSort2(int[] a, int fromIndex, int toIndex){
        int x = a[(fromIndex + toIndex) / 2]; 
        int i = fromIndex; 
        int j = toIndex; 
        int[] b = new int[] {x,i,j};
        insertionSort(b);
        x = b[1];
        while (i <= j) { // カーソルの位置関係が逆転しない限りループする
            while (a[i] < x)
                i++;
            while (a[j] > x)
                j--;
            if (i <= j)
                swap(a, i++, j--);
        }
        if (fromIndex < j)
            quickSort2(a, fromIndex, j); // 左側の再帰的なソート
        if (i < toIndex)
            quickSort2(a, i, toIndex); // 右側の再帰的なソート
    }

    public static void quickSort3(int[] a, int fromIndex, int toIndex){
        //要素数で割った値(=gap)を左端から順にたしていく
        //2晩目に大きい値の添え字を戻すようにする
        //未実装(先quickSort2おわってからやる)
    }

    //スワップするメソッド
    public static void swap(int[] a, int idx1, int idx2) {
        int tmp = a[idx1];
        a[idx1] = a[idx2];
        a[idx2] = tmp;
    }

    //要素数を調べるメソッド
    public static int leafValue(int[] a){
        int leaf = 0; //判定値
        int n = a.length;//要素数
        if(1<=n&&n<=6){
            leaf = 1;
            System.out.println("要素数は1~6です.");
        }
        if(n==7){
            leaf = 2;
            System.out.println("要素数は7です.");
        }
        if(8<=n&&n<=40){
            leaf =3;
            System.out.println("要素数は8~40です.");
        }
        if(41<=n){
            leaf = 4;
            System.out.println("要素数は41以上です.");
        }else{
        }
        return leaf;
    }

    //mainメソッド
    public static void main(String[] args) {
        ArraySort array = new ArraySort();
        int[] a = new int[] {8,5,11,2,15,24,1,19};
        System.out.printf("ソート前: %s\n", Arrays.toString(a));
        array.sort(a);
        System.out.printf("ソート後: %s\n", Arrays.toString(a));
    }
}