Média e critério de aprovação

Estou fazendo uma atividade em java para calcular media de três notas e frequência do aluno, onde um dos critérios são:

A saída do programa será um texto com a frequência e a média final do aluno, seguido de uma mensagem referente a sua situação no curso. Exemplo:
Frequencia: 78%
Media final: 6.5

Se o aluno for reprovado por faltas, a mensagem deve ser:
Aluno reprovado por faltas!

a) aluno aprovado com média superior a 9 (não inclusivo):
Aluno aprovado com louvor!

b) aluno aprovado com média superior a 6 (inclusivo) e inferior a 9 (inclusivo):
Aluno aprovado!

c) aluno reprovado com média superior a 4 (inclusivo) e inferior a 6 (não inclusivo):
Aluno de recuperação!

b) aluno reprovado com média inferior a 4 (não inclusivo):
Aluno reprovado!

se a nota for menor que 4 ele estará de recuperação,
Dados as 3 primeira entradas como p1 = 3, p2 = 6 e p3 = 3 e frequência 0,75:

Frequencia: 75%
Media: 3.9
Aluno reprovado! <<< essa seria a saída esperada, mas o que estou obtendo é: Aluno de recuperação!

Segue o código:

package Atividade;
import java.util.*;

public class MediaCriterioAprovacao {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		float frequencia;
		float media, p1, p2, p3;
		
		p1 = sc.nextFloat();
		p2 = sc.nextFloat();
		p3 = sc.nextFloat();
		frequencia = sc.nextFloat();
		
		media = ((p1 * 2) + (p2 * 2) + (p3 * 3)) / 7;
		frequencia = frequencia * 100;        
		System.out.println(media);
		
		if(frequencia >= 75) {
			if(Math.ceil(media) > 9) {
				System.out.printf("Frequencia: %.0f%%\n",frequencia,"%");
				System.out.printf("Media: %.1f\n",media);
				System.out.println("Aluno aprovado com louvor!");
				
			} else if(Math.ceil(media) >= 6 && Math.ceil(media) <= 9) {
				System.out.printf("Frequencia: %.0f%%\n",frequencia,"%");
				System.out.printf("Media: %.1f\n",media);
				System.out.println("Aluno aprovado!");
				
			} else if(Math.ceil(media) >= 4 && Math.ceil(media) < 6) {
				System.out.printf("Frequencia: %.0f%%\n",frequencia,"%");
				System.out.printf("Media: %.1f\n",media);
				System.out.println("Aluno de recuperação!");
				
			} else if(media < 4) {
				System.out.printf("Frequencia: %.0f%%\n",frequencia,"%");
				System.out.printf("Media: %.1f\n",media);
				System.out.println("Aluno reprovado!");
			}
		} else {
			System.out.printf("Frequencia: %.0f%%\n",frequencia,"%");
			System.out.printf("Media: %.1f\n",media);
			System.out.println("Aluno reprovado por faltas!");
		}
	}
}

Quando você utiliza o ceil, você está forçando o arredondamento “para cima”. Logo, se a tua média for 3.9, por exemplo, o retorno desse método será 4.0. Assim sendo, a condição

media < 4

Só será contemplada para notas < 3.5, na verdade.

Ou você remove o Math.ceil ou você altera a sequência das validações lógicas, colocando a verificação de reprovação antes de todas.

Eu removi Math.ceil e mudei a sequência lógica e ainda continua o mesmo erro

Quando entro com as notas p1 = 3,6 , p2 = 2,4 , p3 = 5,3
media = 4,0, onde era para saída mostrar “aluno em recuperação”, mas ele mostra “aluno reprovado”, mas quando entro com as notas p1 = 4 , p2 = 4 , p3 = 4,
media = 4,0, ai ele mostra “aluno em recuperação”

Não sei em que calculadora você conseguiu fazer com que a soma 3,6 + 2,4 + 5.3 ao ser dividida por 3 dê 4,0. Na minha dá 3,766666666666 que, a não ser que minha matemática esteja errada, é menor que 4 e, sim, se encaixa no if reprovado.

As notas tem o seguinte peso:

p1 tem peso 2, p2 tem peso 2, e p3 tem peso 3
ou seja
nota p1 * 2, nota p2 * 2, nota p3 * 3, somando as três notas e dividindo por 3.