Poland secured second place in Group C with Fiorentina winger Jakub Blaszczykowski, but Ukraine caused a few scares.
They will face Switzerland in the Round of 16.
Ukraine were already well aware of their status at the bottom of Group C and made several changes to the line-up for this final group game. Poland brought in Piotr Zielinski and Bartosz Kaputska, but Roma goalkeeper Wojciech Szczesny was again injured.
Poland dominated from the get-go and had three clear-cut chances within five minutes, Andriy Pyatov beating away efforts from Akradiusz Milik and Robert Lewandowski.
Ukraine were surprisingly dangerous on the counter and Michal Pazdan performed a last-ditch tackle on Roman Zozulya, but Andriy Yarmolenko missed a sitter when failing to curl in with his left boot.
After the restart, Olexandr Zinchenko turned a free header over the bar before Poland finally broke through with substitute Jakub Blaszczykowski. On a short corner he cut in past Ruslan Rotan and curled a fantastic finish into the far top corner.
It should’ve been 2-0 moments later, but Bartosz Kaputska hit the side-netting after a counter with Lewandowski.
However, Ukraine weren’t going down without a fight and forced Lukasz Fabianski into saves late on with Rotan and Yarmolenko.
Ukraine 0-1 Poland
Blaszczykowski 54 (P)
Ukraine: Pyatov; Fedetskiy, Khacheridi, Kucher, Butko; Rotan, Stepanenko; Yarmolenko, Zinchenko (Kovalenko 73), Konoplyanka; Zozulya (Tymoshchuk 92)
Poland: Fabianski; Jedrzejczyk, Pazdan, Glik, Cionek; Kaputska (Krosicki 71), Krychowiak, Jodlowiec, Zielinski (Blaszczykowski 46); Milik (Starzynski 93); Lewandowski
Ref: Moen (NOR)