Stop thinking about classes for a while and think only in terms of "objects". In object-oriented programming, everything is an object, not a class. A class is simply a detailed description or a blueprint, that is all. In a JRE, at runtime, there are only objects. Note, when you start to code static classes and methods you start to move away from object-oriented programming and into structured programming.
It seems like this could further be class aggregation since there is a whole/part relationship - an instance of the Student class would be part of the whole Course class but it seems like a Student class could live outside of the Course class. Read the rest of this post to understand my confusion regarding class aggregation vs object aggregation.
If in "your" application, a Student object can exists without an owning Course object, then there isn't a Composition relationship between the two objects. This would be an example of an Aggregation relationship.
If in "your" application, a Student object cannot exist without an owning Course object, there there is a Composition relationship.
but it seems like a Student class could live outside of the Course class
If you write the code that makes this happen, then it happens. If you don't write the code then it doesn't happen. How do you determine what to do and how to design? You need to carefully read the business requirements of the application. Here in the requirements you will learn if a Student object can exist outside of a Course object.
If you don't have requirements, then you could
run wild with you theories and hypothetical scenarios...